diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-01-14 15:38:35 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-01-14 15:38:35 +0000 |
commit | d2e0a8dd949ab874c6d66f97106bd5c270e2fa7d (patch) | |
tree | e8a99a0386e8f6bece630700da5915c8a312c2d9 | |
parent | fdc82ccb3f2b23a89e7002fe8238e1422b00f96a (diff) |
Notes
224 files changed, 12944 insertions, 823 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index c09b75f990e5..c56707e7fb57 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,7 +16,8 @@ if( CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR ) "--libdir" "--includedir" "--prefix" - "--src-root") + "--src-root" + "--cmakedir") execute_process( COMMAND ${CONFIG_COMMAND} RESULT_VARIABLE HAD_ERROR @@ -41,6 +42,7 @@ if( CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR ) list(GET CONFIG_OUTPUT 3 INCLUDE_DIR) list(GET CONFIG_OUTPUT 4 LLVM_OBJ_ROOT) list(GET CONFIG_OUTPUT 5 MAIN_SRC_DIR) + list(GET CONFIG_OUTPUT 6 LLVM_CMAKE_PATH) if(NOT MSVC_IDE) set(LLVM_ENABLE_ASSERTIONS ${ENABLE_ASSERTIONS} @@ -58,7 +60,6 @@ if( CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR ) find_program(LLVM_TABLEGEN_EXE "llvm-tblgen" ${LLVM_TOOLS_BINARY_DIR} NO_DEFAULT_PATH) - set(LLVM_CMAKE_PATH "${LLVM_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX}/cmake/llvm") set(LLVMCONFIG_FILE "${LLVM_CMAKE_PATH}/LLVMConfig.cmake") if(EXISTS ${LLVMCONFIG_FILE}) list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_PATH}") diff --git a/bindings/python/clang/cindex.py b/bindings/python/clang/cindex.py index c22d2510c62c..c1c7590fe9f3 100644 --- a/bindings/python/clang/cindex.py +++ b/bindings/python/clang/cindex.py @@ -64,7 +64,6 @@ call is efficient. from ctypes import * import collections -import sys import clang.enumerations @@ -74,33 +73,6 @@ import clang.enumerations # this by marshalling object arguments as void**. c_object_p = POINTER(c_void_p) -if sys.version_info[0] > 2: -# Python 3 strings are unicode, translate them to/from utf8 for C-interop -# Python 3 replaces xrange with range, we want xrange behaviour - xrange = range - - class c_string_p(c_char_p): - def __init__(self, p=None): - if type(p) == str: - p = p.encode("utf8") - super(c_char_p, self).__init__(p) - - def __str__(self): - return str(self.value) - - @property - def value(self): - if super(c_char_p, self).value is None: - return None - return super(c_char_p, self).value.decode("utf8") - - @classmethod - def from_param(cls, param): - return cls(param) -else: - c_string_p = c_char_p - - callbacks = {} ### Exception Classes ### @@ -175,7 +147,7 @@ class CachedProperty(object): class _CXString(Structure): """Helper for transforming CXString results.""" - _fields_ = [("spelling", c_string_p), ("free", c_int)] + _fields_ = [("spelling", c_char_p), ("free", c_int)] def __del__(self): conf.lib.clang_disposeString(self) @@ -357,7 +329,7 @@ class Diagnostic(object): @property def spelling(self): - return str(conf.lib.clang_getDiagnosticSpelling(self)) + return conf.lib.clang_getDiagnosticSpelling(self) @property def ranges(self): @@ -386,8 +358,8 @@ class Diagnostic(object): def __getitem__(self, key): range = SourceRange() - value = str(conf.lib.clang_getDiagnosticFixIt(self.diag, key, - byref(range))) + value = conf.lib.clang_getDiagnosticFixIt(self.diag, key, + byref(range)) if len(value) == 0: raise IndexError @@ -420,12 +392,12 @@ class Diagnostic(object): @property def category_name(self): """The string name of the category for this diagnostic.""" - return str(conf.lib.clang_getDiagnosticCategoryText(self)) + return conf.lib.clang_getDiagnosticCategoryText(self) @property def option(self): """The command-line option that enables this diagnostic.""" - return str(conf.lib.clang_getDiagnosticOption(self, None)) + return conf.lib.clang_getDiagnosticOption(self, None) @property def disable_option(self): @@ -433,7 +405,7 @@ class Diagnostic(object): disable = _CXString() conf.lib.clang_getDiagnosticOption(self, byref(disable)) - return str(conf.lib.clang_getCString(disable)) + return conf.lib.clang_getCString(disable) def format(self, options=None): """ @@ -582,8 +554,8 @@ class BaseEnumeration(object): if value >= len(self.__class__._kinds): self.__class__._kinds += [None] * (value - len(self.__class__._kinds) + 1) if self.__class__._kinds[value] is not None: - raise ValueError('{0} value {1} already loaded'.format( - str(self.__class__), value)) + raise ValueError,'{0} value {1} already loaded'.format( + str(self.__class__), value) self.value = value self.__class__._kinds[value] = self self.__class__._name_map = None @@ -600,12 +572,12 @@ class BaseEnumeration(object): for key, value in self.__class__.__dict__.items(): if isinstance(value, self.__class__): self._name_map[value] = key - return str(self._name_map[self]) + return self._name_map[self] @classmethod def from_id(cls, id): if id >= len(cls._kinds) or cls._kinds[id] is None: - raise ValueError('Unknown template argument kind %d' % id) + raise ValueError,'Unknown template argument kind %d' % id return cls._kinds[id] def __repr__(self): @@ -624,7 +596,7 @@ class CursorKind(BaseEnumeration): @staticmethod def get_all_kinds(): """Return all CursorKind enumeration instances.""" - return [x for x in CursorKind._kinds if x] + return filter(None, CursorKind._kinds) def is_declaration(self): """Test if this is a declaration kind.""" @@ -1457,9 +1429,9 @@ class Cursor(Structure): def spelling(self): """Return the spelling of the entity pointed at by the cursor.""" if not hasattr(self, '_spelling'): - self._spelling = str(conf.lib.clang_getCursorSpelling(self)) + self._spelling = conf.lib.clang_getCursorSpelling(self) - return str(self._spelling) + return self._spelling @property def displayname(self): @@ -1471,7 +1443,7 @@ class Cursor(Structure): arguments of a class template specialization. """ if not hasattr(self, '_displayname'): - self._displayname = str(conf.lib.clang_getCursorDisplayName(self)) + self._displayname = conf.lib.clang_getCursorDisplayName(self) return self._displayname @@ -1479,7 +1451,7 @@ class Cursor(Structure): def mangled_name(self): """Return the mangled name for the entity referenced by this cursor.""" if not hasattr(self, '_mangled_name'): - self._mangled_name = str(conf.lib.clang_Cursor_getMangling(self)) + self._mangled_name = conf.lib.clang_Cursor_getMangling(self) return self._mangled_name @@ -1618,7 +1590,7 @@ class Cursor(Structure): self._objc_type_encoding = \ conf.lib.clang_getDeclObjCTypeEncoding(self) - return str(self._objc_type_encoding) + return self._objc_type_encoding @property def hash(self): @@ -1665,23 +1637,17 @@ class Cursor(Structure): @property def brief_comment(self): """Returns the brief comment text associated with that Cursor""" - r = conf.lib.clang_Cursor_getBriefCommentText(self) - if not r: - return None - return str(r) + return conf.lib.clang_Cursor_getBriefCommentText(self) @property def raw_comment(self): """Returns the raw comment text associated with that Cursor""" - r = conf.lib.clang_Cursor_getRawCommentText(self) - if not r: - return None - return str(r) + return conf.lib.clang_Cursor_getRawCommentText(self) def get_arguments(self): """Return an iterator for accessing the arguments of this cursor.""" num_args = conf.lib.clang_Cursor_getNumArguments(self) - for i in xrange(0, num_args): + for i in range(0, num_args): yield conf.lib.clang_Cursor_getArgument(self, i) def get_num_template_arguments(self): @@ -1811,7 +1777,7 @@ class StorageClass(object): if value >= len(StorageClass._kinds): StorageClass._kinds += [None] * (value - len(StorageClass._kinds) + 1) if StorageClass._kinds[value] is not None: - raise ValueError('StorageClass already loaded') + raise ValueError,'StorageClass already loaded' self.value = value StorageClass._kinds[value] = self StorageClass._name_map = None @@ -1832,7 +1798,7 @@ class StorageClass(object): @staticmethod def from_id(id): if id >= len(StorageClass._kinds) or not StorageClass._kinds[id]: - raise ValueError('Unknown storage class %d' % id) + raise ValueError,'Unknown storage class %d' % id return StorageClass._kinds[id] def __repr__(self): @@ -1885,7 +1851,7 @@ class TypeKind(BaseEnumeration): @property def spelling(self): """Retrieve the spelling of this TypeKind.""" - return str(conf.lib.clang_getTypeKindSpelling(self.value)) + return conf.lib.clang_getTypeKindSpelling(self.value) def __repr__(self): return 'TypeKind.%s' % (self.name,) @@ -2161,7 +2127,7 @@ class Type(Structure): """ Retrieve the offset of a field in the record. """ - return conf.lib.clang_Type_getOffsetOf(self, fieldname) + return conf.lib.clang_Type_getOffsetOf(self, c_char_p(fieldname)) def get_ref_qualifier(self): """ @@ -2188,7 +2154,7 @@ class Type(Structure): @property def spelling(self): """Retrieve the spelling of this Type.""" - return str(conf.lib.clang_getTypeSpelling(self)) + return conf.lib.clang_getTypeSpelling(self) def __eq__(self, other): if type(other) != type(self): @@ -2220,7 +2186,7 @@ class ClangObject(object): class _CXUnsavedFile(Structure): """Helper for passing unsaved file arguments.""" - _fields_ = [("name", c_string_p), ("contents", c_string_p), ('length', c_ulong)] + _fields_ = [("name", c_char_p), ("contents", c_char_p), ('length', c_ulong)] # Functions calls through the python interface are rather slow. Fortunately, # for most symboles, we do not need to perform a function call. Their spelling @@ -2266,7 +2232,7 @@ class CompletionChunk: self.__kindNumberCache = -1 def __repr__(self): - return "{'" + str(self.spelling) + "', " + str(self.kind) + "}" + return "{'" + self.spelling + "', " + str(self.kind) + "}" @CachedProperty def spelling(self): @@ -2575,9 +2541,7 @@ class TranslationUnit(ClangObject): args_array = None if len(args) > 0: - args_array = (c_string_p * len(args))() - for i,a in enumerate(args): - args_array[i] = c_string_p(a) + args_array = (c_char_p * len(args))(* args) unsaved_array = None if len(unsaved_files) > 0: @@ -2586,8 +2550,8 @@ class TranslationUnit(ClangObject): if hasattr(contents, "read"): contents = contents.read() - unsaved_array[i].name = c_string_p(name) - unsaved_array[i].contents = c_string_p(contents) + unsaved_array[i].name = name + unsaved_array[i].contents = contents unsaved_array[i].length = len(contents) ptr = conf.lib.clang_parseTranslationUnit(index, filename, args_array, @@ -2642,7 +2606,7 @@ class TranslationUnit(ClangObject): @property def spelling(self): """Get the original translation unit source file name.""" - return str(conf.lib.clang_getTranslationUnitSpelling(self)) + return conf.lib.clang_getTranslationUnitSpelling(self) def get_includes(self): """ @@ -2765,9 +2729,9 @@ class TranslationUnit(ClangObject): # FIXME: It would be great to support an efficient version # of this, one day. value = value.read() - print(value) + print value if not isinstance(value, str): - raise TypeError('Unexpected unsaved file contents.') + raise TypeError,'Unexpected unsaved file contents.' unsaved_files_array[i].name = name unsaved_files_array[i].contents = value unsaved_files_array[i].length = len(value) @@ -2829,11 +2793,11 @@ class TranslationUnit(ClangObject): # FIXME: It would be great to support an efficient version # of this, one day. value = value.read() - print(value) + print value if not isinstance(value, str): - raise TypeError('Unexpected unsaved file contents.') - unsaved_files_array[i].name = c_string_p(name) - unsaved_files_array[i].contents = c_string_p(value) + raise TypeError,'Unexpected unsaved file contents.' + unsaved_files_array[i].name = name + unsaved_files_array[i].contents = value unsaved_files_array[i].length = len(value) ptr = conf.lib.clang_codeCompleteAt(self, path, line, column, unsaved_files_array, len(unsaved_files), options) @@ -2868,7 +2832,7 @@ class File(ClangObject): @property def name(self): """Return the complete file and path name of the file.""" - return str(conf.lib.clang_getCString(conf.lib.clang_getFileName(self))) + return conf.lib.clang_getCString(conf.lib.clang_getFileName(self)) @property def time(self): @@ -2876,7 +2840,7 @@ class File(ClangObject): return conf.lib.clang_getFileTime(self) def __str__(self): - return str(self.name) + return self.name def __repr__(self): return "<File: %s>" % (self.name) @@ -2945,12 +2909,12 @@ class CompileCommand(object): @property def directory(self): """Get the working directory for this CompileCommand""" - return str(conf.lib.clang_CompileCommand_getDirectory(self.cmd)) + return conf.lib.clang_CompileCommand_getDirectory(self.cmd) @property def filename(self): """Get the working filename for this CompileCommand""" - return str(conf.lib.clang_CompileCommand_getFilename(self.cmd)) + return conf.lib.clang_CompileCommand_getFilename(self.cmd) @property def arguments(self): @@ -2962,7 +2926,7 @@ class CompileCommand(object): """ length = conf.lib.clang_CompileCommand_getNumArgs(self.cmd) for i in xrange(length): - yield str(conf.lib.clang_CompileCommand_getArg(self.cmd, i)) + yield conf.lib.clang_CompileCommand_getArg(self.cmd, i) class CompileCommands(object): """ @@ -3056,7 +3020,7 @@ class Token(Structure): This is the textual representation of the token in source. """ - return str(conf.lib.clang_getTokenSpelling(self._tu, self)) + return conf.lib.clang_getTokenSpelling(self._tu, self) @property def kind(self): @@ -3099,7 +3063,7 @@ functionList = [ [c_object_p]), ("clang_CompilationDatabase_fromDirectory", - [c_string_p, POINTER(c_uint)], + [c_char_p, POINTER(c_uint)], c_object_p, CompilationDatabase.from_result), @@ -3109,7 +3073,7 @@ functionList = [ CompileCommands.from_result), ("clang_CompilationDatabase_getCompileCommands", - [c_object_p, c_string_p], + [c_object_p, c_char_p], c_object_p, CompileCommands.from_result), @@ -3144,7 +3108,7 @@ functionList = [ c_uint), ("clang_codeCompleteAt", - [TranslationUnit, c_string_p, c_int, c_int, c_void_p, c_int, c_int], + [TranslationUnit, c_char_p, c_int, c_int, c_void_p, c_int, c_int], POINTER(CCRStructure)), ("clang_codeCompleteGetDiagnostic", @@ -3160,7 +3124,7 @@ functionList = [ c_object_p), ("clang_createTranslationUnit", - [Index, c_string_p], + [Index, c_char_p], c_object_p), ("clang_CXXConstructor_isConvertingConstructor", @@ -3310,7 +3274,7 @@ functionList = [ ("clang_getCString", [_CXString], - c_string_p), + c_char_p), ("clang_getCursor", [TranslationUnit, SourceLocation], @@ -3457,7 +3421,7 @@ functionList = [ Type.from_result), ("clang_getFile", - [TranslationUnit, c_string_p], + [TranslationUnit, c_char_p], c_object_p), ("clang_getFileName", @@ -3586,7 +3550,7 @@ functionList = [ ("clang_getTUResourceUsageName", [c_uint], - c_string_p), + c_char_p), ("clang_getTypeDeclaration", [Type], @@ -3681,7 +3645,7 @@ functionList = [ bool), ("clang_parseTranslationUnit", - [Index, c_string_p, c_void_p, c_int, c_void_p, c_int, c_int], + [Index, c_char_p, c_void_p, c_int, c_void_p, c_int, c_int], c_object_p), ("clang_reparseTranslationUnit", @@ -3689,7 +3653,7 @@ functionList = [ c_int), ("clang_saveTranslationUnit", - [TranslationUnit, c_string_p, c_uint], + [TranslationUnit, c_char_p, c_uint], c_int), ("clang_tokenize", @@ -3761,7 +3725,7 @@ functionList = [ Type.from_result), ("clang_Type_getOffsetOf", - [Type, c_string_p], + [Type, c_char_p], c_longlong), ("clang_Type_getSizeOf", @@ -3820,8 +3784,7 @@ def register_functions(lib, ignore_errors): def register(item): return register_function(lib, item, ignore_errors) - for f in functionList: - register(f) + map(register, functionList) class Config: library_path = None diff --git a/bindings/python/tests/cindex/test_translation_unit.py b/bindings/python/tests/cindex/test_translation_unit.py index f959cf4aafcc..be6cd671ae0c 100644 --- a/bindings/python/tests/cindex/test_translation_unit.py +++ b/bindings/python/tests/cindex/test_translation_unit.py @@ -59,13 +59,9 @@ int SOME_DEFINE; assert spellings[-1] == 'y' def test_unsaved_files_2(): - try: - from StringIO import StringIO - except: - from io import StringIO - + import StringIO tu = TranslationUnit.from_source('fake.c', unsaved_files = [ - ('fake.c', StringIO('int x;'))]) + ('fake.c', StringIO.StringIO('int x;'))]) spellings = [c.spelling for c in tu.cursor.get_children()] assert spellings[-1] == 'x' diff --git a/docs/AttributeReference.rst b/docs/AttributeReference.rst index a763ddeaeb10..d7a3f74f83fb 100644 --- a/docs/AttributeReference.rst +++ b/docs/AttributeReference.rst @@ -1,13 +1,3118 @@ .. ------------------------------------------------------------------- NOTE: This file is automatically generated by running clang-tblgen - -gen-attr-docs. Do not edit this file by hand!! The contents for - this file are automatically generated by a server-side process. - - Please do not commit this file. The file exists for local testing - purposes only. + -gen-attr-docs. Do not edit this file by hand!! ------------------------------------------------------------------- =================== Attributes in Clang -===================
\ No newline at end of file +=================== +.. contents:: + :local: + +Introduction +============ + +This page lists the attributes currently supported by Clang. + +Function Attributes +=================== + + +interrupt +--------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","","","", "" + +Clang supports the GNU style ``__attribute__((interrupt("TYPE")))`` attribute on +ARM targets. This attribute may be attached to a function definition and +instructs the backend to generate appropriate function entry/exit code so that +it can be used directly as an interrupt service routine. + +The parameter passed to the interrupt attribute is optional, but if +provided it must be a string literal with one of the following values: "IRQ", +"FIQ", "SWI", "ABORT", "UNDEF". + +The semantics are as follows: + +- If the function is AAPCS, Clang instructs the backend to realign the stack to + 8 bytes on entry. This is a general requirement of the AAPCS at public + interfaces, but may not hold when an exception is taken. Doing this allows + other AAPCS functions to be called. +- If the CPU is M-class this is all that needs to be done since the architecture + itself is designed in such a way that functions obeying the normal AAPCS ABI + constraints are valid exception handlers. +- If the CPU is not M-class, the prologue and epilogue are modified to save all + non-banked registers that are used, so that upon return the user-mode state + will not be corrupted. Note that to avoid unnecessary overhead, only + general-purpose (integer) registers are saved in this way. If VFP operations + are needed, that state must be saved manually. + + Specifically, interrupt kinds other than "FIQ" will save all core registers + except "lr" and "sp". "FIQ" interrupts will save r0-r7. +- If the CPU is not M-class, the return instruction is changed to one of the + canonical sequences permitted by the architecture for exception return. Where + possible the function itself will make the necessary "lr" adjustments so that + the "preferred return address" is selected. + + Unfortunately the compiler is unable to make this guarantee for an "UNDEF" + handler, where the offset from "lr" to the preferred return address depends on + the execution state of the code which generated the exception. In this case + a sequence equivalent to "movs pc, lr" will be used. + + +abi_tag (gnu::abi_tag) +---------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","X","","", "" + +The ``abi_tag`` attribute can be applied to a function, variable, class or +inline namespace declaration to modify the mangled name of the entity. It gives +the ability to distinguish between different versions of the same entity but +with different ABI versions supported. For example, a newer version of a class +could have a different set of data members and thus have a different size. Using +the ``abi_tag`` attribute, it is possible to have different mangled names for +a global variable of the class type. Therefor, the old code could keep using +the old manged name and the new code will use the new mangled name with tags. + + +acquire_capability (acquire_shared_capability, clang::acquire_capability, clang::acquire_shared_capability) +----------------------------------------------------------------------------------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","X","","", "" + +Marks a function as acquiring a capability. + + +alloc_size (gnu::alloc_size) +---------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","X","","", "" + +The ``alloc_size`` attribute can be placed on functions that return pointers in +order to hint to the compiler how many bytes of memory will be available at the +returned poiner. ``alloc_size`` takes one or two arguments. + +- ``alloc_size(N)`` implies that argument number N equals the number of + available bytes at the returned pointer. +- ``alloc_size(N, M)`` implies that the product of argument number N and + argument number M equals the number of available bytes at the returned + pointer. + +Argument numbers are 1-based. + +An example of how to use ``alloc_size`` + +.. code-block:: c + + void *my_malloc(int a) __attribute__((alloc_size(1))); + void *my_calloc(int a, int b) __attribute__((alloc_size(1, 2))); + + int main() { + void *const p = my_malloc(100); + assert(__builtin_object_size(p, 0) == 100); + void *const a = my_calloc(20, 5); + assert(__builtin_object_size(a, 0) == 100); + } + +.. Note:: This attribute works differently in clang than it does in GCC. + Specifically, clang will only trace ``const`` pointers (as above); we give up + on pointers that are not marked as ``const``. In the vast majority of cases, + this is unimportant, because LLVM has support for the ``alloc_size`` + attribute. However, this may cause mildly unintuitive behavior when used with + other attributes, such as ``enable_if``. + + +interrupt +--------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","","","", "" + +Clang supports the GNU style ``__attribute__((interrupt))`` attribute on +x86/x86-64 targets.The compiler generates function entry and exit sequences +suitable for use in an interrupt handler when this attribute is present. +The 'IRET' instruction, instead of the 'RET' instruction, is used to return +from interrupt or exception handlers. All registers, except for the EFLAGS +register which is restored by the 'IRET' instruction, are preserved by the +compiler. + +Any interruptible-without-stack-switch code must be compiled with +-mno-red-zone since interrupt handlers can and will, because of the +hardware design, touch the red zone. + +1. interrupt handler must be declared with a mandatory pointer argument: + + .. code-block:: c + + struct interrupt_frame + { + uword_t ip; + uword_t cs; + uword_t flags; + uword_t sp; + uword_t ss; + }; + + __attribute__ ((interrupt)) + void f (struct interrupt_frame *frame) { + ... + } + +2. exception handler: + + The exception handler is very similar to the interrupt handler with + a different mandatory function signature: + + .. code-block:: c + + __attribute__ ((interrupt)) + void f (struct interrupt_frame *frame, uword_t error_code) { + ... + } + + and compiler pops 'ERROR_CODE' off stack before the 'IRET' instruction. + + The exception handler should only be used for exceptions which push an + error code and all other exceptions must use the interrupt handler. + The system will crash if the wrong handler is used. + + +assert_capability (assert_shared_capability, clang::assert_capability, clang::assert_shared_capability) +------------------------------------------------------------------------------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","X","","", "" + +Marks a function that dynamically tests whether a capability is held, and halts +the program if it is not held. + + +assume_aligned (gnu::assume_aligned) +------------------------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","X","","", "" + +Use ``__attribute__((assume_aligned(<alignment>[,<offset>]))`` on a function +declaration to specify that the return value of the function (which must be a +pointer type) has the specified offset, in bytes, from an address with the +specified alignment. The offset is taken to be zero if omitted. + +.. code-block:: c++ + + // The returned pointer value has 32-byte alignment. + void *a() __attribute__((assume_aligned (32))); + + // The returned pointer value is 4 bytes greater than an address having + // 32-byte alignment. + void *b() __attribute__((assume_aligned (32, 4))); + +Note that this attribute provides information to the compiler regarding a +condition that the code already ensures is true. It does not cause the compiler +to enforce the provided alignment assumption. + + +availability +------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","","","", "" + +The ``availability`` attribute can be placed on declarations to describe the +lifecycle of that declaration relative to operating system versions. Consider +the function declaration for a hypothetical function ``f``: + +.. code-block:: c++ + + void f(void) __attribute__((availability(macos,introduced=10.4,deprecated=10.6,obsoleted=10.7))); + +The availability attribute states that ``f`` was introduced in Mac OS X 10.4, +deprecated in Mac OS X 10.6, and obsoleted in Mac OS X 10.7. This information +is used by Clang to determine when it is safe to use ``f``: for example, if +Clang is instructed to compile code for Mac OS X 10.5, a call to ``f()`` +succeeds. If Clang is instructed to compile code for Mac OS X 10.6, the call +succeeds but Clang emits a warning specifying that the function is deprecated. +Finally, if Clang is instructed to compile code for Mac OS X 10.7, the call +fails because ``f()`` is no longer available. + +The availability attribute is a comma-separated list starting with the +platform name and then including clauses specifying important milestones in the +declaration's lifetime (in any order) along with additional information. Those +clauses can be: + +introduced=\ *version* + The first version in which this declaration was introduced. + +deprecated=\ *version* + The first version in which this declaration was deprecated, meaning that + users should migrate away from this API. + +obsoleted=\ *version* + The first version in which this declaration was obsoleted, meaning that it + was removed completely and can no longer be used. + +unavailable + This declaration is never available on this platform. + +message=\ *string-literal* + Additional message text that Clang will provide when emitting a warning or + error about use of a deprecated or obsoleted declaration. Useful to direct + users to replacement APIs. + +replacement=\ *string-literal* + Additional message text that Clang will use to provide Fix-It when emitting + a warning about use of a deprecated declaration. The Fix-It will replace + the deprecated declaration with the new declaration specified. + +Multiple availability attributes can be placed on a declaration, which may +correspond to different platforms. Only the availability attribute with the +platform corresponding to the target platform will be used; any others will be +ignored. If no availability attribute specifies availability for the current +target platform, the availability attributes are ignored. Supported platforms +are: + +``ios`` + Apple's iOS operating system. The minimum deployment target is specified by + the ``-mios-version-min=*version*`` or ``-miphoneos-version-min=*version*`` + command-line arguments. + +``macos`` + Apple's Mac OS X operating system. The minimum deployment target is + specified by the ``-mmacosx-version-min=*version*`` command-line argument. + ``macosx`` is supported for backward-compatibility reasons, but it is + deprecated. + +``tvos`` + Apple's tvOS operating system. The minimum deployment target is specified by + the ``-mtvos-version-min=*version*`` command-line argument. + +``watchos`` + Apple's watchOS operating system. The minimum deployment target is specified by + the ``-mwatchos-version-min=*version*`` command-line argument. + +A declaration can typically be used even when deploying back to a platform +version prior to when the declaration was introduced. When this happens, the +declaration is `weakly linked +<https://developer.apple.com/library/mac/#documentation/MacOSX/Conceptual/BPFrameworks/Concepts/WeakLinking.html>`_, +as if the ``weak_import`` attribute were added to the declaration. A +weakly-linked declaration may or may not be present a run-time, and a program +can determine whether the declaration is present by checking whether the +address of that declaration is non-NULL. + +The flag ``strict`` disallows using API when deploying back to a +platform version prior to when the declaration was introduced. An +attempt to use such API before its introduction causes a hard error. +Weakly-linking is almost always a better API choice, since it allows +users to query availability at runtime. + +If there are multiple declarations of the same entity, the availability +attributes must either match on a per-platform basis or later +declarations must not have availability attributes for that +platform. For example: + +.. code-block:: c + + void g(void) __attribute__((availability(macos,introduced=10.4))); + void g(void) __attribute__((availability(macos,introduced=10.4))); // okay, matches + void g(void) __attribute__((availability(ios,introduced=4.0))); // okay, adds a new platform + void g(void); // okay, inherits both macos and ios availability from above. + void g(void) __attribute__((availability(macos,introduced=10.5))); // error: mismatch + +When one method overrides another, the overriding method can be more widely available than the overridden method, e.g.,: + +.. code-block:: objc + + @interface A + - (id)method __attribute__((availability(macos,introduced=10.4))); + - (id)method2 __attribute__((availability(macos,introduced=10.4))); + @end + + @interface B : A + - (id)method __attribute__((availability(macos,introduced=10.3))); // okay: method moved into base class later + - (id)method __attribute__((availability(macos,introduced=10.5))); // error: this method was available via the base class in 10.4 + @end + + +_Noreturn +--------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "","","","X", "" + +A function declared as ``_Noreturn`` shall not return to its caller. The +compiler will generate a diagnostic for a function declared as ``_Noreturn`` +that appears to be capable of returning to its caller. + + +noreturn +-------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "","X","","", "" + +A function declared as ``[[noreturn]]`` shall not return to its caller. The +compiler will generate a diagnostic for a function declared as ``[[noreturn]]`` +that appears to be capable of returning to its caller. + + +carries_dependency +------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","X","","", "" + +The ``carries_dependency`` attribute specifies dependency propagation into and +out of functions. + +When specified on a function or Objective-C method, the ``carries_dependency`` +attribute means that the return value carries a dependency out of the function, +so that the implementation need not constrain ordering upon return from that +function. Implementations of the function and its caller may choose to preserve +dependencies instead of emitting memory ordering instructions such as fences. + +Note, this attribute does not change the meaning of the program, but may result +in generation of more efficient code. + + +convergent (clang::convergent) +------------------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","X","","", "" + +The ``convergent`` attribute can be placed on a function declaration. It is +translated into the LLVM ``convergent`` attribute, which indicates that the call +instructions of a function with this attribute cannot be made control-dependent +on any additional values. + +In languages designed for SPMD/SIMT programming model, e.g. OpenCL or CUDA, +the call instructions of a function with this attribute must be executed by +all work items or threads in a work group or sub group. + +This attribute is different from ``noduplicate`` because it allows duplicating +function calls if it can be proved that the duplicated function calls are +not made control-dependent on any additional values, e.g., unrolling a loop +executed by all work items. + +Sample usage: +.. code-block:: c + + void convfunc(void) __attribute__((convergent)); + // Setting it as a C++11 attribute is also valid in a C++ program. + // void convfunc(void) [[clang::convergent]]; + + +deprecated (gnu::deprecated) +---------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","X","X","", "" + +The ``deprecated`` attribute can be applied to a function, a variable, or a +type. This is useful when identifying functions, variables, or types that are +expected to be removed in a future version of a program. + +Consider the function declaration for a hypothetical function ``f``: + +.. code-block:: c++ + + void f(void) __attribute__((deprecated("message", "replacement"))); + +When spelled as `__attribute__((deprecated))`, the deprecated attribute can have +two optional string arguments. The first one is the message to display when +emitting the warning; the second one enables the compiler to provide a Fix-It +to replace the deprecated name with a new name. Otherwise, when spelled as +`[[gnu::deprecated]] or [[deprecated]]`, the attribute can have one optional +string argument which is the message to display when emitting the warning. + + +diagnose_if +----------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","","","", "" + +The ``diagnose_if`` attribute can be placed on function declarations to emit +warnings or errors at compile-time if calls to the attributed function meet +certain user-defined criteria. For example: + +.. code-block:: c + void abs(int a) + __attribute__((diagnose_if(a >= 0, "Redundant abs call", "warning"))); + void must_abs(int a) + __attribute__((diagnose_if(a >= 0, "Redundant abs call", "error"))); + + int val = abs(1); // warning: Redundant abs call + int val2 = must_abs(1); // error: Redundant abs call + int val3 = abs(val); + int val4 = must_abs(val); // Because run-time checks are not emitted for + // diagnose_if attributes, this executes without + // issue. + + +``diagnose_if`` is closely related to ``enable_if``, with a few key differences: + +* Overload resolution is not aware of ``diagnose_if`` attributes: they're + considered only after we select the best candidate from a given candidate set. +* Function declarations that differ only in their ``diagnose_if`` attributes are + considered to be redeclarations of the same function (not overloads). +* If the condition provided to ``diagnose_if`` cannot be evaluated, no + diagnostic will be emitted. + +Otherwise, ``diagnose_if`` is essentially the logical negation of ``enable_if``. + +As a result of bullet number two, ``diagnose_if`` attributes will stack on the +same function. For example: + +.. code-block:: c + + int foo() __attribute__((diagnose_if(1, "diag1", "warning"))); + int foo() __attribute__((diagnose_if(1, "diag2", "warning"))); + + int bar = foo(); // warning: diag1 + // warning: diag2 + int (*fooptr)(void) = foo; // warning: diag1 + // warning: diag2 + + constexpr int supportsAPILevel(int N) { return N < 5; } + int baz(int a) + __attribute__((diagnose_if(!supportsAPILevel(10), + "Upgrade to API level 10 to use baz", "error"))); + int baz(int a) + __attribute__((diagnose_if(!a, "0 is not recommended.", "warning"))); + + int (*bazptr)(int) = baz; // error: Upgrade to API level 10 to use baz + int v = baz(0); // error: Upgrade to API level 10 to use baz + +Query for this feature with ``__has_attribute(diagnose_if)``. + + +disable_tail_calls (clang::disable_tail_calls) +---------------------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","X","","", "" + +The ``disable_tail_calls`` attribute instructs the backend to not perform tail call optimization inside the marked function. + +For example: + + .. code-block:: c + + int callee(int); + + int foo(int a) __attribute__((disable_tail_calls)) { + return callee(a); // This call is not tail-call optimized. + } + +Marking virtual functions as ``disable_tail_calls`` is legal. + + .. code-block:: c++ + + int callee(int); + + class Base { + public: + [[clang::disable_tail_calls]] virtual int foo1() { + return callee(); // This call is not tail-call optimized. + } + }; + + class Derived1 : public Base { + public: + int foo1() override { + return callee(); // This call is tail-call optimized. + } + }; + + +enable_if +--------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","","","", "" + +.. Note:: Some features of this attribute are experimental. The meaning of + multiple enable_if attributes on a single declaration is subject to change in + a future version of clang. Also, the ABI is not standardized and the name + mangling may change in future versions. To avoid that, use asm labels. + +The ``enable_if`` attribute can be placed on function declarations to control +which overload is selected based on the values of the function's arguments. +When combined with the ``overloadable`` attribute, this feature is also +available in C. + +.. code-block:: c++ + + int isdigit(int c); + int isdigit(int c) __attribute__((enable_if(c <= -1 || c > 255, "chosen when 'c' is out of range"))) __attribute__((unavailable("'c' must have the value of an unsigned char or EOF"))); + + void foo(char c) { + isdigit(c); + isdigit(10); + isdigit(-10); // results in a compile-time error. + } + +The enable_if attribute takes two arguments, the first is an expression written +in terms of the function parameters, the second is a string explaining why this +overload candidate could not be selected to be displayed in diagnostics. The +expression is part of the function signature for the purposes of determining +whether it is a redeclaration (following the rules used when determining +whether a C++ template specialization is ODR-equivalent), but is not part of +the type. + +The enable_if expression is evaluated as if it were the body of a +bool-returning constexpr function declared with the arguments of the function +it is being applied to, then called with the parameters at the call site. If the +result is false or could not be determined through constant expression +evaluation, then this overload will not be chosen and the provided string may +be used in a diagnostic if the compile fails as a result. + +Because the enable_if expression is an unevaluated context, there are no global +state changes, nor the ability to pass information from the enable_if +expression to the function body. For example, suppose we want calls to +strnlen(strbuf, maxlen) to resolve to strnlen_chk(strbuf, maxlen, size of +strbuf) only if the size of strbuf can be determined: + +.. code-block:: c++ + + __attribute__((always_inline)) + static inline size_t strnlen(const char *s, size_t maxlen) + __attribute__((overloadable)) + __attribute__((enable_if(__builtin_object_size(s, 0) != -1))), + "chosen when the buffer size is known but 'maxlen' is not"))) + { + return strnlen_chk(s, maxlen, __builtin_object_size(s, 0)); + } + +Multiple enable_if attributes may be applied to a single declaration. In this +case, the enable_if expressions are evaluated from left to right in the +following manner. First, the candidates whose enable_if expressions evaluate to +false or cannot be evaluated are discarded. If the remaining candidates do not +share ODR-equivalent enable_if expressions, the overload resolution is +ambiguous. Otherwise, enable_if overload resolution continues with the next +enable_if attribute on the candidates that have not been discarded and have +remaining enable_if attributes. In this way, we pick the most specific +overload out of a number of viable overloads using enable_if. + +.. code-block:: c++ + + void f() __attribute__((enable_if(true, ""))); // #1 + void f() __attribute__((enable_if(true, ""))) __attribute__((enable_if(true, ""))); // #2 + + void g(int i, int j) __attribute__((enable_if(i, ""))); // #1 + void g(int i, int j) __attribute__((enable_if(j, ""))) __attribute__((enable_if(true))); // #2 + +In this example, a call to f() is always resolved to #2, as the first enable_if +expression is ODR-equivalent for both declarations, but #1 does not have another +enable_if expression to continue evaluating, so the next round of evaluation has +only a single candidate. In a call to g(1, 1), the call is ambiguous even though +#2 has more enable_if attributes, because the first enable_if expressions are +not ODR-equivalent. + +Query for this feature with ``__has_attribute(enable_if)``. + +Note that functions with one or more ``enable_if`` attributes may not have +their address taken, unless all of the conditions specified by said +``enable_if`` are constants that evaluate to ``true``. For example: + +.. code-block:: c + + const int TrueConstant = 1; + const int FalseConstant = 0; + int f(int a) __attribute__((enable_if(a > 0, ""))); + int g(int a) __attribute__((enable_if(a == 0 || a != 0, ""))); + int h(int a) __attribute__((enable_if(1, ""))); + int i(int a) __attribute__((enable_if(TrueConstant, ""))); + int j(int a) __attribute__((enable_if(FalseConstant, ""))); + + void fn() { + int (*ptr)(int); + ptr = &f; // error: 'a > 0' is not always true + ptr = &g; // error: 'a == 0 || a != 0' is not a truthy constant + ptr = &h; // OK: 1 is a truthy constant + ptr = &i; // OK: 'TrueConstant' is a truthy constant + ptr = &j; // error: 'FalseConstant' is a constant, but not truthy + } + +Because ``enable_if`` evaluation happens during overload resolution, +``enable_if`` may give unintuitive results when used with templates, depending +on when overloads are resolved. In the example below, clang will emit a +diagnostic about no viable overloads for ``foo`` in ``bar``, but not in ``baz``: + +.. code-block:: c++ + + double foo(int i) __attribute__((enable_if(i > 0, ""))); + void *foo(int i) __attribute__((enable_if(i <= 0, ""))); + template <int I> + auto bar() { return foo(I); } + + template <typename T> + auto baz() { return foo(T::number); } + + struct WithNumber { constexpr static int number = 1; }; + void callThem() { + bar<sizeof(WithNumber)>(); + baz<WithNumber>(); + } + +This is because, in ``bar``, ``foo`` is resolved prior to template +instantiation, so the value for ``I`` isn't known (thus, both ``enable_if`` +conditions for ``foo`` fail). However, in ``baz``, ``foo`` is resolved during +template instantiation, so the value for ``T::number`` is known. + + +flatten (gnu::flatten) +---------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","X","","", "" + +The ``flatten`` attribute causes calls within the attributed function to +be inlined unless it is impossible to do so, for example if the body of the +callee is unavailable or if the callee has the ``noinline`` attribute. + + +format (gnu::format) +-------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","X","","", "" + +Clang supports the ``format`` attribute, which indicates that the function +accepts a ``printf`` or ``scanf``-like format string and corresponding +arguments or a ``va_list`` that contains these arguments. + +Please see `GCC documentation about format attribute +<http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html>`_ to find details +about attribute syntax. + +Clang implements two kinds of checks with this attribute. + +#. Clang checks that the function with the ``format`` attribute is called with + a format string that uses format specifiers that are allowed, and that + arguments match the format string. This is the ``-Wformat`` warning, it is + on by default. + +#. Clang checks that the format string argument is a literal string. This is + the ``-Wformat-nonliteral`` warning, it is off by default. + + Clang implements this mostly the same way as GCC, but there is a difference + for functions that accept a ``va_list`` argument (for example, ``vprintf``). + GCC does not emit ``-Wformat-nonliteral`` warning for calls to such + functions. Clang does not warn if the format string comes from a function + parameter, where the function is annotated with a compatible attribute, + otherwise it warns. For example: + + .. code-block:: c + + __attribute__((__format__ (__scanf__, 1, 3))) + void foo(const char* s, char *buf, ...) { + va_list ap; + va_start(ap, buf); + + vprintf(s, ap); // warning: format string is not a string literal + } + + In this case we warn because ``s`` contains a format string for a + ``scanf``-like function, but it is passed to a ``printf``-like function. + + If the attribute is removed, clang still warns, because the format string is + not a string literal. + + Another example: + + .. code-block:: c + + __attribute__((__format__ (__printf__, 1, 3))) + void foo(const char* s, char *buf, ...) { + va_list ap; + va_start(ap, buf); + + vprintf(s, ap); // warning + } + + In this case Clang does not warn because the format string ``s`` and + the corresponding arguments are annotated. If the arguments are + incorrect, the caller of ``foo`` will receive a warning. + + +ifunc (gnu::ifunc) +------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","X","","", "" + +``__attribute__((ifunc("resolver")))`` is used to mark that the address of a declaration should be resolved at runtime by calling a resolver function. + +The symbol name of the resolver function is given in quotes. A function with this name (after mangling) must be defined in the current translation unit; it may be ``static``. The resolver function should take no arguments and return a pointer. + +The ``ifunc`` attribute may only be used on a function declaration. A function declaration with an ``ifunc`` attribute is considered to be a definition of the declared entity. The entity must not have weak linkage; for example, in C++, it cannot be applied to a declaration if a definition at that location would be considered inline. + +Not all targets support this attribute. ELF targets support this attribute when using binutils v2.20.1 or higher and glibc v2.11.1 or higher. Non-ELF targets currently do not support this attribute. + + +internal_linkage (clang::internal_linkage) +------------------------------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","X","","", "" + +The ``internal_linkage`` attribute changes the linkage type of the declaration to internal. +This is similar to C-style ``static``, but can be used on classes and class methods. When applied to a class definition, +this attribute affects all methods and static data members of that class. +This can be used to contain the ABI of a C++ library by excluding unwanted class methods from the export tables. + + +interrupt +--------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","","","", "" + +Clang supports the GNU style ``__attribute__((interrupt("ARGUMENT")))`` attribute on +MIPS targets. This attribute may be attached to a function definition and instructs +the backend to generate appropriate function entry/exit code so that it can be used +directly as an interrupt service routine. + +By default, the compiler will produce a function prologue and epilogue suitable for +an interrupt service routine that handles an External Interrupt Controller (eic) +generated interrupt. This behaviour can be explicitly requested with the "eic" +argument. + +Otherwise, for use with vectored interrupt mode, the argument passed should be +of the form "vector=LEVEL" where LEVEL is one of the following values: +"sw0", "sw1", "hw0", "hw1", "hw2", "hw3", "hw4", "hw5". The compiler will +then set the interrupt mask to the corresponding level which will mask all +interrupts up to and including the argument. + +The semantics are as follows: + +- The prologue is modified so that the Exception Program Counter (EPC) and + Status coprocessor registers are saved to the stack. The interrupt mask is + set so that the function can only be interrupted by a higher priority + interrupt. The epilogue will restore the previous values of EPC and Status. + +- The prologue and epilogue are modified to save and restore all non-kernel + registers as necessary. + +- The FPU is disabled in the prologue, as the floating pointer registers are not + spilled to the stack. + +- The function return sequence is changed to use an exception return instruction. + +- The parameter sets the interrupt mask for the function corresponding to the + interrupt level specified. If no mask is specified the interrupt mask + defaults to "eic". + + +noalias +------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "","","X","", "" + +The ``noalias`` attribute indicates that the only memory accesses inside +function are loads and stores from objects pointed to by its pointer-typed +arguments, with arbitrary offsets. + + +noduplicate (clang::noduplicate) +-------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","X","","", "" + +The ``noduplicate`` attribute can be placed on function declarations to control +whether function calls to this function can be duplicated or not as a result of +optimizations. This is required for the implementation of functions with +certain special requirements, like the OpenCL "barrier" function, that might +need to be run concurrently by all the threads that are executing in lockstep +on the hardware. For example this attribute applied on the function +"nodupfunc" in the code below avoids that: + +.. code-block:: c + + void nodupfunc() __attribute__((noduplicate)); + // Setting it as a C++11 attribute is also valid + // void nodupfunc() [[clang::noduplicate]]; + void foo(); + void bar(); + + nodupfunc(); + if (a > n) { + foo(); + } else { + bar(); + } + +gets possibly modified by some optimizations into code similar to this: + +.. code-block:: c + + if (a > n) { + nodupfunc(); + foo(); + } else { + nodupfunc(); + bar(); + } + +where the call to "nodupfunc" is duplicated and sunk into the two branches +of the condition. + + +no_sanitize (clang::no_sanitize) +-------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","X","","", "" + +Use the ``no_sanitize`` attribute on a function declaration to specify +that a particular instrumentation or set of instrumentations should not be +applied to that function. The attribute takes a list of string literals, +which have the same meaning as values accepted by the ``-fno-sanitize=`` +flag. For example, ``__attribute__((no_sanitize("address", "thread")))`` +specifies that AddressSanitizer and ThreadSanitizer should not be applied +to the function. + +See :ref:`Controlling Code Generation <controlling-code-generation>` for a +full list of supported sanitizer flags. + + +no_sanitize_address (no_address_safety_analysis, gnu::no_address_safety_analysis, gnu::no_sanitize_address) +----------------------------------------------------------------------------------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","X","","", "" + +.. _langext-address_sanitizer: + +Use ``__attribute__((no_sanitize_address))`` on a function declaration to +specify that address safety instrumentation (e.g. AddressSanitizer) should +not be applied to that function. + + +no_sanitize_thread +------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","X","","", "" + +.. _langext-thread_sanitizer: + +Use ``__attribute__((no_sanitize_thread))`` on a function declaration to +specify that checks for data races on plain (non-atomic) memory accesses should +not be inserted by ThreadSanitizer. The function is still instrumented by the +tool to avoid false positives and provide meaningful stack traces. + + +no_sanitize_memory +------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","X","","", "" + +.. _langext-memory_sanitizer: + +Use ``__attribute__((no_sanitize_memory))`` on a function declaration to +specify that checks for uninitialized memory should not be inserted +(e.g. by MemorySanitizer). The function may still be instrumented by the tool +to avoid false positives in other places. + + +no_split_stack (gnu::no_split_stack) +------------------------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","X","","", "" + +The ``no_split_stack`` attribute disables the emission of the split stack +preamble for a particular function. It has no effect if ``-fsplit-stack`` +is not specified. + + +not_tail_called (clang::not_tail_called) +---------------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","X","","", "" + +The ``not_tail_called`` attribute prevents tail-call optimization on statically bound calls. It has no effect on indirect calls. Virtual functions, objective-c methods, and functions marked as ``always_inline`` cannot be marked as ``not_tail_called``. + +For example, it prevents tail-call optimization in the following case: + + .. code-block:: c + + int __attribute__((not_tail_called)) foo1(int); + + int foo2(int a) { + return foo1(a); // No tail-call optimization on direct calls. + } + +However, it doesn't prevent tail-call optimization in this case: + + .. code-block:: c + + int __attribute__((not_tail_called)) foo1(int); + + int foo2(int a) { + int (*fn)(int) = &foo1; + + // not_tail_called has no effect on an indirect call even if the call can be + // resolved at compile time. + return (*fn)(a); + } + +Marking virtual functions as ``not_tail_called`` is an error: + + .. code-block:: c++ + + class Base { + public: + // not_tail_called on a virtual function is an error. + [[clang::not_tail_called]] virtual int foo1(); + + virtual int foo2(); + + // Non-virtual functions can be marked ``not_tail_called``. + [[clang::not_tail_called]] int foo3(); + }; + + class Derived1 : public Base { + public: + int foo1() override; + + // not_tail_called on a virtual function is an error. + [[clang::not_tail_called]] int foo2() override; + }; + + +#pragma omp declare simd +------------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "","","","", "X" + +The `declare simd` construct can be applied to a function to enable the creation +of one or more versions that can process multiple arguments using SIMD +instructions from a single invocation in a SIMD loop. The `declare simd` +directive is a declarative directive. There may be multiple `declare simd` +directives for a function. The use of a `declare simd` construct on a function +enables the creation of SIMD versions of the associated function that can be +used to process multiple arguments from a single invocation from a SIMD loop +concurrently. +The syntax of the `declare simd` construct is as follows: + + .. code-block:: c + + #pragma omp declare simd [clause[[,] clause] ...] new-line + [#pragma omp declare simd [clause[[,] clause] ...] new-line] + [...] + function definition or declaration + +where clause is one of the following: + + .. code-block:: c + + simdlen(length) + linear(argument-list[:constant-linear-step]) + aligned(argument-list[:alignment]) + uniform(argument-list) + inbranch + notinbranch + + +#pragma omp declare target +-------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "","","","", "X" + +The `declare target` directive specifies that variables and functions are mapped +to a device for OpenMP offload mechanism. + +The syntax of the declare target directive is as follows: + + .. code-block:: c + + #pragma omp declare target new-line + declarations-definition-seq + #pragma omp end declare target new-line + + +objc_boxable +------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","","","", "" + +Structs and unions marked with the ``objc_boxable`` attribute can be used +with the Objective-C boxed expression syntax, ``@(...)``. + +**Usage**: ``__attribute__((objc_boxable))``. This attribute +can only be placed on a declaration of a trivially-copyable struct or union: + +.. code-block:: objc + + struct __attribute__((objc_boxable)) some_struct { + int i; + }; + union __attribute__((objc_boxable)) some_union { + int i; + float f; + }; + typedef struct __attribute__((objc_boxable)) _some_struct some_struct; + + // ... + + some_struct ss; + NSValue *boxed = @(ss); + + +objc_method_family +------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","","","", "" + +Many methods in Objective-C have conventional meanings determined by their +selectors. It is sometimes useful to be able to mark a method as having a +particular conventional meaning despite not having the right selector, or as +not having the conventional meaning that its selector would suggest. For these +use cases, we provide an attribute to specifically describe the "method family" +that a method belongs to. + +**Usage**: ``__attribute__((objc_method_family(X)))``, where ``X`` is one of +``none``, ``alloc``, ``copy``, ``init``, ``mutableCopy``, or ``new``. This +attribute can only be placed at the end of a method declaration: + +.. code-block:: objc + + - (NSString *)initMyStringValue __attribute__((objc_method_family(none))); + +Users who do not wish to change the conventional meaning of a method, and who +merely want to document its non-standard retain and release semantics, should +use the retaining behavior attributes (``ns_returns_retained``, +``ns_returns_not_retained``, etc). + +Query for this feature with ``__has_attribute(objc_method_family)``. + + +objc_requires_super +------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","","","", "" + +Some Objective-C classes allow a subclass to override a particular method in a +parent class but expect that the overriding method also calls the overridden +method in the parent class. For these cases, we provide an attribute to +designate that a method requires a "call to ``super``" in the overriding +method in the subclass. + +**Usage**: ``__attribute__((objc_requires_super))``. This attribute can only +be placed at the end of a method declaration: + +.. code-block:: objc + + - (void)foo __attribute__((objc_requires_super)); + +This attribute can only be applied the method declarations within a class, and +not a protocol. Currently this attribute does not enforce any placement of +where the call occurs in the overriding method (such as in the case of +``-dealloc`` where the call must appear at the end). It checks only that it +exists. + +Note that on both OS X and iOS that the Foundation framework provides a +convenience macro ``NS_REQUIRES_SUPER`` that provides syntactic sugar for this +attribute: + +.. code-block:: objc + + - (void)foo NS_REQUIRES_SUPER; + +This macro is conditionally defined depending on the compiler's support for +this attribute. If the compiler does not support the attribute the macro +expands to nothing. + +Operationally, when a method has this annotation the compiler will warn if the +implementation of an override in a subclass does not call super. For example: + +.. code-block:: objc + + warning: method possibly missing a [super AnnotMeth] call + - (void) AnnotMeth{}; + ^ + + +objc_runtime_name +----------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","","","", "" + +By default, the Objective-C interface or protocol identifier is used +in the metadata name for that object. The `objc_runtime_name` +attribute allows annotated interfaces or protocols to use the +specified string argument in the object's metadata name instead of the +default name. + +**Usage**: ``__attribute__((objc_runtime_name("MyLocalName")))``. This attribute +can only be placed before an @protocol or @interface declaration: + +.. code-block:: objc + + __attribute__((objc_runtime_name("MyLocalName"))) + @interface Message + @end + + +objc_runtime_visible +-------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","","","", "" + +This attribute specifies that the Objective-C class to which it applies is visible to the Objective-C runtime but not to the linker. Classes annotated with this attribute cannot be subclassed and cannot have categories defined for them. + + +optnone (clang::optnone) +------------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","X","","", "" + +The ``optnone`` attribute suppresses essentially all optimizations +on a function or method, regardless of the optimization level applied to +the compilation unit as a whole. This is particularly useful when you +need to debug a particular function, but it is infeasible to build the +entire application without optimization. Avoiding optimization on the +specified function can improve the quality of the debugging information +for that function. + +This attribute is incompatible with the ``always_inline`` and ``minsize`` +attributes. + + +overloadable +------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","","","", "" + +Clang provides support for C++ function overloading in C. Function overloading +in C is introduced using the ``overloadable`` attribute. For example, one +might provide several overloaded versions of a ``tgsin`` function that invokes +the appropriate standard function computing the sine of a value with ``float``, +``double``, or ``long double`` precision: + +.. code-block:: c + + #include <math.h> + float __attribute__((overloadable)) tgsin(float x) { return sinf(x); } + double __attribute__((overloadable)) tgsin(double x) { return sin(x); } + long double __attribute__((overloadable)) tgsin(long double x) { return sinl(x); } + +Given these declarations, one can call ``tgsin`` with a ``float`` value to +receive a ``float`` result, with a ``double`` to receive a ``double`` result, +etc. Function overloading in C follows the rules of C++ function overloading +to pick the best overload given the call arguments, with a few C-specific +semantics: + +* Conversion from ``float`` or ``double`` to ``long double`` is ranked as a + floating-point promotion (per C99) rather than as a floating-point conversion + (as in C++). + +* A conversion from a pointer of type ``T*`` to a pointer of type ``U*`` is + considered a pointer conversion (with conversion rank) if ``T`` and ``U`` are + compatible types. + +* A conversion from type ``T`` to a value of type ``U`` is permitted if ``T`` + and ``U`` are compatible types. This conversion is given "conversion" rank. + +* If no viable candidates are otherwise available, we allow a conversion from a + pointer of type ``T*`` to a pointer of type ``U*``, where ``T`` and ``U`` are + incompatible. This conversion is ranked below all other types of conversions. + Please note: ``U`` lacking qualifiers that are present on ``T`` is sufficient + for ``T`` and ``U`` to be incompatible. + +The declaration of ``overloadable`` functions is restricted to function +declarations and definitions. Most importantly, if any function with a given +name is given the ``overloadable`` attribute, then all function declarations +and definitions with that name (and in that scope) must have the +``overloadable`` attribute. This rule even applies to redeclarations of +functions whose original declaration had the ``overloadable`` attribute, e.g., + +.. code-block:: c + + int f(int) __attribute__((overloadable)); + float f(float); // error: declaration of "f" must have the "overloadable" attribute + + int g(int) __attribute__((overloadable)); + int g(int) { } // error: redeclaration of "g" must also have the "overloadable" attribute + +Functions marked ``overloadable`` must have prototypes. Therefore, the +following code is ill-formed: + +.. code-block:: c + + int h() __attribute__((overloadable)); // error: h does not have a prototype + +However, ``overloadable`` functions are allowed to use a ellipsis even if there +are no named parameters (as is permitted in C++). This feature is particularly +useful when combined with the ``unavailable`` attribute: + +.. code-block:: c++ + + void honeypot(...) __attribute__((overloadable, unavailable)); // calling me is an error + +Functions declared with the ``overloadable`` attribute have their names mangled +according to the same rules as C++ function names. For example, the three +``tgsin`` functions in our motivating example get the mangled names +``_Z5tgsinf``, ``_Z5tgsind``, and ``_Z5tgsine``, respectively. There are two +caveats to this use of name mangling: + +* Future versions of Clang may change the name mangling of functions overloaded + in C, so you should not depend on an specific mangling. To be completely + safe, we strongly urge the use of ``static inline`` with ``overloadable`` + functions. + +* The ``overloadable`` attribute has almost no meaning when used in C++, + because names will already be mangled and functions are already overloadable. + However, when an ``overloadable`` function occurs within an ``extern "C"`` + linkage specification, it's name *will* be mangled in the same way as it + would in C. + +Query for this feature with ``__has_extension(attribute_overloadable)``. + + +release_capability (release_shared_capability, clang::release_capability, clang::release_shared_capability) +----------------------------------------------------------------------------------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","X","","", "" + +Marks a function as releasing a capability. + + +kernel +------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","","","", "" + +``__attribute__((kernel))`` is used to mark a ``kernel`` function in +RenderScript. + +In RenderScript, ``kernel`` functions are used to express data-parallel +computations. The RenderScript runtime efficiently parallelizes ``kernel`` +functions to run on computational resources such as multi-core CPUs and GPUs. +See the RenderScript_ documentation for more information. + +.. _RenderScript: https://developer.android.com/guide/topics/renderscript/compute.html + + +target (gnu::target) +-------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","X","","", "" + +Clang supports the GNU style ``__attribute__((target("OPTIONS")))`` attribute. +This attribute may be attached to a function definition and instructs +the backend to use different code generation options than were passed on the +command line. + +The current set of options correspond to the existing "subtarget features" for +the target with or without a "-mno-" in front corresponding to the absence +of the feature, as well as ``arch="CPU"`` which will change the default "CPU" +for the function. + +Example "subtarget features" from the x86 backend include: "mmx", "sse", "sse4.2", +"avx", "xop" and largely correspond to the machine specific options handled by +the front end. + + +try_acquire_capability (try_acquire_shared_capability, clang::try_acquire_capability, clang::try_acquire_shared_capability) +--------------------------------------------------------------------------------------------------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","X","","", "" + +Marks a function that attempts to acquire a capability. This function may fail to +actually acquire the capability; they accept a Boolean value determining +whether acquiring the capability means success (true), or failing to acquire +the capability means success (false). + + +nodiscard, warn_unused_result, clang::warn_unused_result, gnu::warn_unused_result +--------------------------------------------------------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","X","","", "" + +Clang supports the ability to diagnose when the results of a function call +expression are discarded under suspicious circumstances. A diagnostic is +generated when a function or its return type is marked with ``[[nodiscard]]`` +(or ``__attribute__((warn_unused_result))``) and the function call appears as a +potentially-evaluated discarded-value expression that is not explicitly cast to +`void`. + +.. code-block: c++ + struct [[nodiscard]] error_info { /*...*/ }; + error_info enable_missile_safety_mode(); + + void launch_missiles(); + void test_missiles() { + enable_missile_safety_mode(); // diagnoses + launch_missiles(); + } + error_info &foo(); + void f() { foo(); } // Does not diagnose, error_info is a reference. + + +xray_always_instrument (clang::xray_always_instrument), xray_never_instrument (clang::xray_never_instrument) +------------------------------------------------------------------------------------------------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","X","","", "" + +``__attribute__((xray_always_instrument))`` or ``[[clang::xray_always_instrument]]`` is used to mark member functions (in C++), methods (in Objective C), and free functions (in C, C++, and Objective C) to be instrumented with XRay. This will cause the function to always have space at the beginning and exit points to allow for runtime patching. + +Conversely, ``__attribute__((xray_never_instrument))`` or ``[[clang::xray_never_instrument]]`` will inhibit the insertion of these instrumentation points. + +If a function has neither of these attributes, they become subject to the XRay heuristics used to determine whether a function should be instrumented or otherwise. + + +Variable Attributes +=================== + + +dllexport (gnu::dllexport) +-------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","X","X","", "" + +The ``__declspec(dllexport)`` attribute declares a variable, function, or +Objective-C interface to be exported from the module. It is available under the +``-fdeclspec`` flag for compatibility with various compilers. The primary use +is for COFF object files which explicitly specify what interfaces are available +for external use. See the dllexport_ documentation on MSDN for more +information. + +.. _dllexport: https://msdn.microsoft.com/en-us/library/3y1sfaz2.aspx + + +dllimport (gnu::dllimport) +-------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","X","X","", "" + +The ``__declspec(dllimport)`` attribute declares a variable, function, or +Objective-C interface to be imported from an external module. It is available +under the ``-fdeclspec`` flag for compatibility with various compilers. The +primary use is for COFF object files which explicitly specify what interfaces +are imported from external modules. See the dllimport_ documentation on MSDN +for more information. + +.. _dllimport: https://msdn.microsoft.com/en-us/library/3y1sfaz2.aspx + + +init_seg +-------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "","","","", "X" + +The attribute applied by ``pragma init_seg()`` controls the section into +which global initialization function pointers are emitted. It is only +available with ``-fms-extensions``. Typically, this function pointer is +emitted into ``.CRT$XCU`` on Windows. The user can change the order of +initialization by using a different section name with the same +``.CRT$XC`` prefix and a suffix that sorts lexicographically before or +after the standard ``.CRT$XCU`` sections. See the init_seg_ +documentation on MSDN for more information. + +.. _init_seg: http://msdn.microsoft.com/en-us/library/7977wcck(v=vs.110).aspx + + +nodebug (gnu::nodebug) +---------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","X","","", "" + +The ``nodebug`` attribute allows you to suppress debugging information for a +function or method, or for a variable that is not a parameter or a non-static +data member. + + +nosvm +----- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","","","", "" + +OpenCL 2.0 supports the optional ``__attribute__((nosvm))`` qualifier for +pointer variable. It informs the compiler that the pointer does not refer +to a shared virtual memory region. See OpenCL v2.0 s6.7.2 for details. + +Since it is not widely used and has been removed from OpenCL 2.1, it is ignored +by Clang. + + +pass_object_size +---------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","","","", "" + +.. Note:: The mangling of functions with parameters that are annotated with + ``pass_object_size`` is subject to change. You can get around this by + using ``__asm__("foo")`` to explicitly name your functions, thus preserving + your ABI; also, non-overloadable C functions with ``pass_object_size`` are + not mangled. + +The ``pass_object_size(Type)`` attribute can be placed on function parameters to +instruct clang to call ``__builtin_object_size(param, Type)`` at each callsite +of said function, and implicitly pass the result of this call in as an invisible +argument of type ``size_t`` directly after the parameter annotated with +``pass_object_size``. Clang will also replace any calls to +``__builtin_object_size(param, Type)`` in the function by said implicit +parameter. + +Example usage: + +.. code-block:: c + + int bzero1(char *const p __attribute__((pass_object_size(0)))) + __attribute__((noinline)) { + int i = 0; + for (/**/; i < (int)__builtin_object_size(p, 0); ++i) { + p[i] = 0; + } + return i; + } + + int main() { + char chars[100]; + int n = bzero1(&chars[0]); + assert(n == sizeof(chars)); + return 0; + } + +If successfully evaluating ``__builtin_object_size(param, Type)`` at the +callsite is not possible, then the "failed" value is passed in. So, using the +definition of ``bzero1`` from above, the following code would exit cleanly: + +.. code-block:: c + + int main2(int argc, char *argv[]) { + int n = bzero1(argv); + assert(n == -1); + return 0; + } + +``pass_object_size`` plays a part in overload resolution. If two overload +candidates are otherwise equally good, then the overload with one or more +parameters with ``pass_object_size`` is preferred. This implies that the choice +between two identical overloads both with ``pass_object_size`` on one or more +parameters will always be ambiguous; for this reason, having two such overloads +is illegal. For example: + +.. code-block:: c++ + + #define PS(N) __attribute__((pass_object_size(N))) + // OK + void Foo(char *a, char *b); // Overload A + // OK -- overload A has no parameters with pass_object_size. + void Foo(char *a PS(0), char *b PS(0)); // Overload B + // Error -- Same signature (sans pass_object_size) as overload B, and both + // overloads have one or more parameters with the pass_object_size attribute. + void Foo(void *a PS(0), void *b); + + // OK + void Bar(void *a PS(0)); // Overload C + // OK + void Bar(char *c PS(1)); // Overload D + + void main() { + char known[10], *unknown; + Foo(unknown, unknown); // Calls overload B + Foo(known, unknown); // Calls overload B + Foo(unknown, known); // Calls overload B + Foo(known, known); // Calls overload B + + Bar(known); // Calls overload D + Bar(unknown); // Calls overload D + } + +Currently, ``pass_object_size`` is a bit restricted in terms of its usage: + +* Only one use of ``pass_object_size`` is allowed per parameter. + +* It is an error to take the address of a function with ``pass_object_size`` on + any of its parameters. If you wish to do this, you can create an overload + without ``pass_object_size`` on any parameters. + +* It is an error to apply the ``pass_object_size`` attribute to parameters that + are not pointers. Additionally, any parameter that ``pass_object_size`` is + applied to must be marked ``const`` at its function's definition. + + +require_constant_initialization (clang::require_constant_initialization) +------------------------------------------------------------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","X","","", "" + +This attribute specifies that the variable to which it is attached is intended +to have a `constant initializer <http://en.cppreference.com/w/cpp/language/constant_initialization>`_ +according to the rules of [basic.start.static]. The variable is required to +have static or thread storage duration. If the initialization of the variable +is not a constant initializer an error will be produced. This attribute may +only be used in C++. + +Note that in C++03 strict constant expression checking is not done. Instead +the attribute reports if Clang can emit the variable as a constant, even if it's +not technically a 'constant initializer'. This behavior is non-portable. + +Static storage duration variables with constant initializers avoid hard-to-find +bugs caused by the indeterminate order of dynamic initialization. They can also +be safely used during dynamic initialization across translation units. + +This attribute acts as a compile time assertion that the requirements +for constant initialization have been met. Since these requirements change +between dialects and have subtle pitfalls it's important to fail fast instead +of silently falling back on dynamic initialization. + +.. code-block:: c++ + + // -std=c++14 + #define SAFE_STATIC [[clang::require_constant_initialization]] + struct T { + constexpr T(int) {} + ~T(); // non-trivial + }; + SAFE_STATIC T x = {42}; // Initialization OK. Doesn't check destructor. + SAFE_STATIC T y = 42; // error: variable does not have a constant initializer + // copy initialization is not a constant expression on a non-literal type. + + +section (gnu::section, __declspec(allocate)) +-------------------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","X","X","", "" + +The ``section`` attribute allows you to specify a specific section a +global variable or function should be in after translation. + + +swiftcall (gnu::swiftcall) +-------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","X","","", "" + +The ``swiftcall`` attribute indicates that a function should be called +using the Swift calling convention for a function or function pointer. + +The lowering for the Swift calling convention, as described by the Swift +ABI documentation, occurs in multiple phases. The first, "high-level" +phase breaks down the formal parameters and results into innately direct +and indirect components, adds implicit paraameters for the generic +signature, and assigns the context and error ABI treatments to parameters +where applicable. The second phase breaks down the direct parameters +and results from the first phase and assigns them to registers or the +stack. The ``swiftcall`` convention only handles this second phase of +lowering; the C function type must accurately reflect the results +of the first phase, as follows: + +- Results classified as indirect by high-level lowering should be + represented as parameters with the ``swift_indirect_result`` attribute. + +- Results classified as direct by high-level lowering should be represented + as follows: + + - First, remove any empty direct results. + + - If there are no direct results, the C result type should be ``void``. + + - If there is one direct result, the C result type should be a type with + the exact layout of that result type. + + - If there are a multiple direct results, the C result type should be + a struct type with the exact layout of a tuple of those results. + +- Parameters classified as indirect by high-level lowering should be + represented as parameters of pointer type. + +- Parameters classified as direct by high-level lowering should be + omitted if they are empty types; otherwise, they should be represented + as a parameter type with a layout exactly matching the layout of the + Swift parameter type. + +- The context parameter, if present, should be represented as a trailing + parameter with the ``swift_context`` attribute. + +- The error result parameter, if present, should be represented as a + trailing parameter (always following a context parameter) with the + ``swift_error_result`` attribute. + +``swiftcall`` does not support variadic arguments or unprototyped functions. + +The parameter ABI treatment attributes are aspects of the function type. +A function type which which applies an ABI treatment attribute to a +parameter is a different type from an otherwise-identical function type +that does not. A single parameter may not have multiple ABI treatment +attributes. + +Support for this feature is target-dependent, although it should be +supported on every target that Swift supports. Query for this support +with ``__has_attribute(swiftcall)``. This implies support for the +``swift_context``, ``swift_error_result``, and ``swift_indirect_result`` +attributes. + + +swift_context (gnu::swift_context) +---------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","X","","", "" + +The ``swift_context`` attribute marks a parameter of a ``swiftcall`` +function as having the special context-parameter ABI treatment. + +This treatment generally passes the context value in a special register +which is normally callee-preserved. + +A ``swift_context`` parameter must either be the last parameter or must be +followed by a ``swift_error_result`` parameter (which itself must always be +the last parameter). + +A context parameter must have pointer or reference type. + + +swift_error_result (gnu::swift_error_result) +-------------------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","X","","", "" + +The ``swift_error_result`` attribute marks a parameter of a ``swiftcall`` +function as having the special error-result ABI treatment. + +This treatment generally passes the underlying error value in and out of +the function through a special register which is normally callee-preserved. +This is modeled in C by pretending that the register is addressable memory: + +- The caller appears to pass the address of a variable of pointer type. + The current value of this variable is copied into the register before + the call; if the call returns normally, the value is copied back into the + variable. + +- The callee appears to receive the address of a variable. This address + is actually a hidden location in its own stack, initialized with the + value of the register upon entry. When the function returns normally, + the value in that hidden location is written back to the register. + +A ``swift_error_result`` parameter must be the last parameter, and it must be +preceded by a ``swift_context`` parameter. + +A ``swift_error_result`` parameter must have type ``T**`` or ``T*&`` for some +type T. Note that no qualifiers are permitted on the intermediate level. + +It is undefined behavior if the caller does not pass a pointer or +reference to a valid object. + +The standard convention is that the error value itself (that is, the +value stored in the apparent argument) will be null upon function entry, +but this is not enforced by the ABI. + + +swift_indirect_result (gnu::swift_indirect_result) +-------------------------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","X","","", "" + +The ``swift_indirect_result`` attribute marks a parameter of a ``swiftcall`` +function as having the special indirect-result ABI treatment. + +This treatment gives the parameter the target's normal indirect-result +ABI treatment, which may involve passing it differently from an ordinary +parameter. However, only the first indirect result will receive this +treatment. Furthermore, low-level lowering may decide that a direct result +must be returned indirectly; if so, this will take priority over the +``swift_indirect_result`` parameters. + +A ``swift_indirect_result`` parameter must either be the first parameter or +follow another ``swift_indirect_result`` parameter. + +A ``swift_indirect_result`` parameter must have type ``T*`` or ``T&`` for +some object type ``T``. If ``T`` is a complete type at the point of +definition of a function, it is undefined behavior if the argument +value does not point to storage of adequate size and alignment for a +value of type ``T``. + +Making indirect results explicit in the signature allows C functions to +directly construct objects into them without relying on language +optimizations like C++'s named return value optimization (NRVO). + + +tls_model (gnu::tls_model) +-------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","X","","", "" + +The ``tls_model`` attribute allows you to specify which thread-local storage +model to use. It accepts the following strings: + +* global-dynamic +* local-dynamic +* initial-exec +* local-exec + +TLS models are mutually exclusive. + + +thread +------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "","","X","", "" + +The ``__declspec(thread)`` attribute declares a variable with thread local +storage. It is available under the ``-fms-extensions`` flag for MSVC +compatibility. See the documentation for `__declspec(thread)`_ on MSDN. + +.. _`__declspec(thread)`: http://msdn.microsoft.com/en-us/library/9w1sdazb.aspx + +In Clang, ``__declspec(thread)`` is generally equivalent in functionality to the +GNU ``__thread`` keyword. The variable must not have a destructor and must have +a constant initializer, if any. The attribute only applies to variables +declared with static storage duration, such as globals, class static data +members, and static locals. + + +maybe_unused, unused, gnu::unused +--------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","X","","", "" + +When passing the ``-Wunused`` flag to Clang, entities that are unused by the +program may be diagnosed. The ``[[maybe_unused]]`` (or +``__attribute__((unused))``) attribute can be used to silence such diagnostics +when the entity cannot be removed. For instance, a local variable may exist +solely for use in an ``assert()`` statement, which makes the local variable +unused when ``NDEBUG`` is defined. + +The attribute may be applied to the declaration of a class, a typedef, a +variable, a function or method, a function parameter, an enumeration, an +enumerator, a non-static data member, or a label. + +.. code-block: c++ + #include <cassert> + + [[maybe_unused]] void f([[maybe_unused]] bool thing1, + [[maybe_unused]] bool thing2) { + [[maybe_unused]] bool b = thing1 && thing2; + assert(b); + } + + +Type Attributes +=============== + + +align_value +----------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","","","", "" + +The align_value attribute can be added to the typedef of a pointer type or the +declaration of a variable of pointer or reference type. It specifies that the +pointer will point to, or the reference will bind to, only objects with at +least the provided alignment. This alignment value must be some positive power +of 2. + + .. code-block:: c + + typedef double * aligned_double_ptr __attribute__((align_value(64))); + void foo(double & x __attribute__((align_value(128)), + aligned_double_ptr y) { ... } + +If the pointer value does not have the specified alignment at runtime, the +behavior of the program is undefined. + + +empty_bases +----------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "","","X","", "" + +The empty_bases attribute permits the compiler to utilize the +empty-base-optimization more frequently. +This attribute only applies to struct, class, and union types. +It is only supported when using the Microsoft C++ ABI. + + +flag_enum +--------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","","","", "" + +This attribute can be added to an enumerator to signal to the compiler that it +is intended to be used as a flag type. This will cause the compiler to assume +that the range of the type includes all of the values that you can get by +manipulating bits of the enumerator when issuing warnings. + + +lto_visibility_public (clang::lto_visibility_public) +---------------------------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "","X","","", "" + +See :doc:`LTOVisibility`. + + +layout_version +-------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "","","X","", "" + +The layout_version attribute requests that the compiler utilize the class +layout rules of a particular compiler version. +This attribute only applies to struct, class, and union types. +It is only supported when using the Microsoft C++ ABI. + + +__single_inhertiance, __multiple_inheritance, __virtual_inheritance +------------------------------------------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "","","","X", "" + +This collection of keywords is enabled under ``-fms-extensions`` and controls +the pointer-to-member representation used on ``*-*-win32`` targets. + +The ``*-*-win32`` targets utilize a pointer-to-member representation which +varies in size and alignment depending on the definition of the underlying +class. + +However, this is problematic when a forward declaration is only available and +no definition has been made yet. In such cases, Clang is forced to utilize the +most general representation that is available to it. + +These keywords make it possible to use a pointer-to-member representation other +than the most general one regardless of whether or not the definition will ever +be present in the current translation unit. + +This family of keywords belong between the ``class-key`` and ``class-name``: + +.. code-block:: c++ + + struct __single_inheritance S; + int S::*i; + struct S {}; + +This keyword can be applied to class templates but only has an effect when used +on full specializations: + +.. code-block:: c++ + + template <typename T, typename U> struct __single_inheritance A; // warning: inheritance model ignored on primary template + template <typename T> struct __multiple_inheritance A<T, T>; // warning: inheritance model ignored on partial specialization + template <> struct __single_inheritance A<int, float>; + +Note that choosing an inheritance model less general than strictly necessary is +an error: + +.. code-block:: c++ + + struct __multiple_inheritance S; // error: inheritance model does not match definition + int S::*i; + struct S {}; + + +novtable +-------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "","","X","", "" + +This attribute can be added to a class declaration or definition to signal to +the compiler that constructors and destructors will not reference the virtual +function table. It is only supported when using the Microsoft C++ ABI. + + +objc_subclassing_restricted +--------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","","","", "" + +This attribute can be added to an Objective-C ``@interface`` declaration to +ensure that this class cannot be subclassed. + + +transparent_union (gnu::transparent_union) +------------------------------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","X","","", "" + +This attribute can be applied to a union to change the behaviour of calls to +functions that have an argument with a transparent union type. The compiler +behaviour is changed in the following manner: + +- A value whose type is any member of the transparent union can be passed as an + argument without the need to cast that value. + +- The argument is passed to the function using the calling convention of the + first member of the transparent union. Consequently, all the members of the + transparent union should have the same calling convention as its first member. + +Transparent unions are not supported in C++. + + +Statement Attributes +==================== + + +fallthrough, clang::fallthrough +------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "","X","","", "" + +The ``fallthrough`` (or ``clang::fallthrough``) attribute is used +to annotate intentional fall-through +between switch labels. It can only be applied to a null statement placed at a +point of execution between any statement and the next switch label. It is +common to mark these places with a specific comment, but this attribute is +meant to replace comments with a more strict annotation, which can be checked +by the compiler. This attribute doesn't change semantics of the code and can +be used wherever an intended fall-through occurs. It is designed to mimic +control-flow statements like ``break;``, so it can be placed in most places +where ``break;`` can, but only if there are no statements on the execution path +between it and the next switch label. + +By default, Clang does not warn on unannotated fallthrough from one ``switch`` +case to another. Diagnostics on fallthrough without a corresponding annotation +can be enabled with the ``-Wimplicit-fallthrough`` argument. + +Here is an example: + +.. code-block:: c++ + + // compile with -Wimplicit-fallthrough + switch (n) { + case 22: + case 33: // no warning: no statements between case labels + f(); + case 44: // warning: unannotated fall-through + g(); + [[clang::fallthrough]]; + case 55: // no warning + if (x) { + h(); + break; + } + else { + i(); + [[clang::fallthrough]]; + } + case 66: // no warning + p(); + [[clang::fallthrough]]; // warning: fallthrough annotation does not + // directly precede case label + q(); + case 77: // warning: unannotated fall-through + r(); + } + + +#pragma clang loop +------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "","","","", "X" + +The ``#pragma clang loop`` directive allows loop optimization hints to be +specified for the subsequent loop. The directive allows vectorization, +interleaving, and unrolling to be enabled or disabled. Vector width as well +as interleave and unrolling count can be manually specified. See +`language extensions +<http://clang.llvm.org/docs/LanguageExtensions.html#extensions-for-loop-hint-optimizations>`_ +for details. + + +#pragma unroll, #pragma nounroll +-------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "","","","", "X" + +Loop unrolling optimization hints can be specified with ``#pragma unroll`` and +``#pragma nounroll``. The pragma is placed immediately before a for, while, +do-while, or c++11 range-based for loop. + +Specifying ``#pragma unroll`` without a parameter directs the loop unroller to +attempt to fully unroll the loop if the trip count is known at compile time and +attempt to partially unroll the loop if the trip count is not known at compile +time: + +.. code-block:: c++ + + #pragma unroll + for (...) { + ... + } + +Specifying the optional parameter, ``#pragma unroll _value_``, directs the +unroller to unroll the loop ``_value_`` times. The parameter may optionally be +enclosed in parentheses: + +.. code-block:: c++ + + #pragma unroll 16 + for (...) { + ... + } + + #pragma unroll(16) + for (...) { + ... + } + +Specifying ``#pragma nounroll`` indicates that the loop should not be unrolled: + +.. code-block:: c++ + + #pragma nounroll + for (...) { + ... + } + +``#pragma unroll`` and ``#pragma unroll _value_`` have identical semantics to +``#pragma clang loop unroll(full)`` and +``#pragma clang loop unroll_count(_value_)`` respectively. ``#pragma nounroll`` +is equivalent to ``#pragma clang loop unroll(disable)``. See +`language extensions +<http://clang.llvm.org/docs/LanguageExtensions.html#extensions-for-loop-hint-optimizations>`_ +for further details including limitations of the unroll hints. + + +__read_only, __write_only, __read_write (read_only, write_only, read_write) +--------------------------------------------------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "","","","X", "" + +The access qualifiers must be used with image object arguments or pipe arguments +to declare if they are being read or written by a kernel or function. + +The read_only/__read_only, write_only/__write_only and read_write/__read_write +names are reserved for use as access qualifiers and shall not be used otherwise. + +.. code-block:: c + + kernel void + foo (read_only image2d_t imageA, + write_only image2d_t imageB) { + ... + } + +In the above example imageA is a read-only 2D image object, and imageB is a +write-only 2D image object. + +The read_write (or __read_write) qualifier can not be used with pipe. + +More details can be found in the OpenCL C language Spec v2.0, Section 6.6. + + +__attribute__((opencl_unroll_hint)) +----------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","","","", "" + +The opencl_unroll_hint attribute qualifier can be used to specify that a loop +(for, while and do loops) can be unrolled. This attribute qualifier can be +used to specify full unrolling or partial unrolling by a specified amount. +This is a compiler hint and the compiler may ignore this directive. See +`OpenCL v2.0 <https://www.khronos.org/registry/cl/specs/opencl-2.0.pdf>`_ +s6.11.5 for details. + + +Type Safety Checking +==================== +Clang supports additional attributes to enable checking type safety properties +that can't be enforced by the C type system. To see warnings produced by these +checks, ensure that -Wtype-safety is enabled. Use cases include: + +* MPI library implementations, where these attributes enable checking that + the buffer type matches the passed ``MPI_Datatype``; +* for HDF5 library there is a similar use case to MPI; +* checking types of variadic functions' arguments for functions like + ``fcntl()`` and ``ioctl()``. + +You can detect support for these attributes with ``__has_attribute()``. For +example: + +.. code-block:: c++ + + #if defined(__has_attribute) + # if __has_attribute(argument_with_type_tag) && \ + __has_attribute(pointer_with_type_tag) && \ + __has_attribute(type_tag_for_datatype) + # define ATTR_MPI_PWT(buffer_idx, type_idx) __attribute__((pointer_with_type_tag(mpi,buffer_idx,type_idx))) + /* ... other macros ... */ + # endif + #endif + + #if !defined(ATTR_MPI_PWT) + # define ATTR_MPI_PWT(buffer_idx, type_idx) + #endif + + int MPI_Send(void *buf, int count, MPI_Datatype datatype /*, other args omitted */) + ATTR_MPI_PWT(1,3); + +argument_with_type_tag +---------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","","","", "" + +Use ``__attribute__((argument_with_type_tag(arg_kind, arg_idx, +type_tag_idx)))`` on a function declaration to specify that the function +accepts a type tag that determines the type of some other argument. + +This attribute is primarily useful for checking arguments of variadic functions +(``pointer_with_type_tag`` can be used in most non-variadic cases). + +In the attribute prototype above: + * ``arg_kind`` is an identifier that should be used when annotating all + applicable type tags. + * ``arg_idx`` provides the position of a function argument. The expected type of + this function argument will be determined by the function argument specified + by ``type_tag_idx``. In the code example below, "3" means that the type of the + function's third argument will be determined by ``type_tag_idx``. + * ``type_tag_idx`` provides the position of a function argument. This function + argument will be a type tag. The type tag will determine the expected type of + the argument specified by ``arg_idx``. In the code example below, "2" means + that the type tag associated with the function's second argument should agree + with the type of the argument specified by ``arg_idx``. + +For example: + +.. code-block:: c++ + + int fcntl(int fd, int cmd, ...) + __attribute__(( argument_with_type_tag(fcntl,3,2) )); + // The function's second argument will be a type tag; this type tag will + // determine the expected type of the function's third argument. + + +pointer_with_type_tag +--------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","","","", "" + +Use ``__attribute__((pointer_with_type_tag(ptr_kind, ptr_idx, type_tag_idx)))`` +on a function declaration to specify that the function accepts a type tag that +determines the pointee type of some other pointer argument. + +In the attribute prototype above: + * ``ptr_kind`` is an identifier that should be used when annotating all + applicable type tags. + * ``ptr_idx`` provides the position of a function argument; this function + argument will have a pointer type. The expected pointee type of this pointer + type will be determined by the function argument specified by + ``type_tag_idx``. In the code example below, "1" means that the pointee type + of the function's first argument will be determined by ``type_tag_idx``. + * ``type_tag_idx`` provides the position of a function argument; this function + argument will be a type tag. The type tag will determine the expected pointee + type of the pointer argument specified by ``ptr_idx``. In the code example + below, "3" means that the type tag associated with the function's third + argument should agree with the pointee type of the pointer argument specified + by ``ptr_idx``. + +For example: + +.. code-block:: c++ + + typedef int MPI_Datatype; + int MPI_Send(void *buf, int count, MPI_Datatype datatype /*, other args omitted */) + __attribute__(( pointer_with_type_tag(mpi,1,3) )); + // The function's 3rd argument will be a type tag; this type tag will + // determine the expected pointee type of the function's 1st argument. + + +type_tag_for_datatype +--------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","","","", "" + +When declaring a variable, use +``__attribute__((type_tag_for_datatype(kind, type)))`` to create a type tag that +is tied to the ``type`` argument given to the attribute. + +In the attribute prototype above: + * ``kind`` is an identifier that should be used when annotating all applicable + type tags. + * ``type`` indicates the name of the type. + +Clang supports annotating type tags of two forms. + + * **Type tag that is a reference to a declared identifier.** + Use ``__attribute__((type_tag_for_datatype(kind, type)))`` when declaring that + identifier: + + .. code-block:: c++ + + typedef int MPI_Datatype; + extern struct mpi_datatype mpi_datatype_int + __attribute__(( type_tag_for_datatype(mpi,int) )); + #define MPI_INT ((MPI_Datatype) &mpi_datatype_int) + // &mpi_datatype_int is a type tag. It is tied to type "int". + + * **Type tag that is an integral literal.** + Declare a ``static const`` variable with an initializer value and attach + ``__attribute__((type_tag_for_datatype(kind, type)))`` on that declaration: + + .. code-block:: c++ + + typedef int MPI_Datatype; + static const MPI_Datatype mpi_datatype_int + __attribute__(( type_tag_for_datatype(mpi,int) )) = 42; + #define MPI_INT ((MPI_Datatype) 42) + // The number 42 is a type tag. It is tied to type "int". + + +The ``type_tag_for_datatype`` attribute also accepts an optional third argument +that determines how the type of the function argument specified by either +``arg_idx`` or ``ptr_idx`` is compared against the type associated with the type +tag. (Recall that for the ``argument_with_type_tag`` attribute, the type of the +function argument specified by ``arg_idx`` is compared against the type +associated with the type tag. Also recall that for the ``pointer_with_type_tag`` +attribute, the pointee type of the function argument specified by ``ptr_idx`` is +compared against the type associated with the type tag.) There are two supported +values for this optional third argument: + + * ``layout_compatible`` will cause types to be compared according to + layout-compatibility rules (In C++11 [class.mem] p 17, 18, see the + layout-compatibility rules for two standard-layout struct types and for two + standard-layout union types). This is useful when creating a type tag + associated with a struct or union type. For example: + + .. code-block:: c++ + + /* In mpi.h */ + typedef int MPI_Datatype; + struct internal_mpi_double_int { double d; int i; }; + extern struct mpi_datatype mpi_datatype_double_int + __attribute__(( type_tag_for_datatype(mpi, + struct internal_mpi_double_int, layout_compatible) )); + + #define MPI_DOUBLE_INT ((MPI_Datatype) &mpi_datatype_double_int) + + int MPI_Send(void *buf, int count, MPI_Datatype datatype, ...) + __attribute__(( pointer_with_type_tag(mpi,1,3) )); + + /* In user code */ + struct my_pair { double a; int b; }; + struct my_pair *buffer; + MPI_Send(buffer, 1, MPI_DOUBLE_INT /*, ... */); // no warning because the + // layout of my_pair is + // compatible with that of + // internal_mpi_double_int + + struct my_int_pair { int a; int b; } + struct my_int_pair *buffer2; + MPI_Send(buffer2, 1, MPI_DOUBLE_INT /*, ... */); // warning because the + // layout of my_int_pair + // does not match that of + // internal_mpi_double_int + + * ``must_be_null`` specifies that the function argument specified by either + ``arg_idx`` (for the ``argument_with_type_tag`` attribute) or ``ptr_idx`` (for + the ``pointer_with_type_tag`` attribute) should be a null pointer constant. + The second argument to the ``type_tag_for_datatype`` attribute is ignored. For + example: + + .. code-block:: c++ + + /* In mpi.h */ + typedef int MPI_Datatype; + extern struct mpi_datatype mpi_datatype_null + __attribute__(( type_tag_for_datatype(mpi, void, must_be_null) )); + + #define MPI_DATATYPE_NULL ((MPI_Datatype) &mpi_datatype_null) + int MPI_Send(void *buf, int count, MPI_Datatype datatype, ...) + __attribute__(( pointer_with_type_tag(mpi,1,3) )); + + /* In user code */ + struct my_pair { double a; int b; }; + struct my_pair *buffer; + MPI_Send(buffer, 1, MPI_DATATYPE_NULL /*, ... */); // warning: MPI_DATATYPE_NULL + // was specified but buffer + // is not a null pointer + + +AMD GPU Attributes +================== + + +amdgpu_flat_work_group_size +--------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","","","", "" + +The flat work-group size is the number of work-items in the work-group size +specified when the kernel is dispatched. It is the product of the sizes of the +x, y, and z dimension of the work-group. + +Clang supports the +``__attribute__((amdgpu_flat_work_group_size(<min>, <max>)))`` attribute for the +AMDGPU target. This attribute may be attached to a kernel function definition +and is an optimization hint. + +``<min>`` parameter specifies the minimum flat work-group size, and ``<max>`` +parameter specifies the maximum flat work-group size (must be greater than +``<min>``) to which all dispatches of the kernel will conform. Passing ``0, 0`` +as ``<min>, <max>`` implies the default behavior (``128, 256``). + +If specified, the AMDGPU target backend might be able to produce better machine +code for barriers and perform scratch promotion by estimating available group +segment size. + +An error will be given if: + - Specified values violate subtarget specifications; + - Specified values are not compatible with values provided through other + attributes. + + +amdgpu_num_sgpr +--------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","","","", "" + +Clang supports the ``__attribute__((amdgpu_num_sgpr(<num_sgpr>)))`` and +``__attribute__((amdgpu_num_vgpr(<num_vgpr>)))`` attributes for the AMDGPU +target. These attributes may be attached to a kernel function definition and are +an optimization hint. + +If these attributes are specified, then the AMDGPU target backend will attempt +to limit the number of SGPRs and/or VGPRs used to the specified value(s). The +number of used SGPRs and/or VGPRs may further be rounded up to satisfy the +allocation requirements or constraints of the subtarget. Passing ``0`` as +``num_sgpr`` and/or ``num_vgpr`` implies the default behavior (no limits). + +These attributes can be used to test the AMDGPU target backend. It is +recommended that the ``amdgpu_waves_per_eu`` attribute be used to control +resources such as SGPRs and VGPRs since it is aware of the limits for different +subtargets. + +An error will be given if: + - Specified values violate subtarget specifications; + - Specified values are not compatible with values provided through other + attributes; + - The AMDGPU target backend is unable to create machine code that can meet the + request. + + +amdgpu_num_vgpr +--------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","","","", "" + +Clang supports the ``__attribute__((amdgpu_num_sgpr(<num_sgpr>)))`` and +``__attribute__((amdgpu_num_vgpr(<num_vgpr>)))`` attributes for the AMDGPU +target. These attributes may be attached to a kernel function definition and are +an optimization hint. + +If these attributes are specified, then the AMDGPU target backend will attempt +to limit the number of SGPRs and/or VGPRs used to the specified value(s). The +number of used SGPRs and/or VGPRs may further be rounded up to satisfy the +allocation requirements or constraints of the subtarget. Passing ``0`` as +``num_sgpr`` and/or ``num_vgpr`` implies the default behavior (no limits). + +These attributes can be used to test the AMDGPU target backend. It is +recommended that the ``amdgpu_waves_per_eu`` attribute be used to control +resources such as SGPRs and VGPRs since it is aware of the limits for different +subtargets. + +An error will be given if: + - Specified values violate subtarget specifications; + - Specified values are not compatible with values provided through other + attributes; + - The AMDGPU target backend is unable to create machine code that can meet the + request. + + +amdgpu_waves_per_eu +------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","","","", "" + +A compute unit (CU) is responsible for executing the wavefronts of a work-group. +It is composed of one or more execution units (EU), which are responsible for +executing the wavefronts. An EU can have enough resources to maintain the state +of more than one executing wavefront. This allows an EU to hide latency by +switching between wavefronts in a similar way to symmetric multithreading on a +CPU. In order to allow the state for multiple wavefronts to fit on an EU, the +resources used by a single wavefront have to be limited. For example, the number +of SGPRs and VGPRs. Limiting such resources can allow greater latency hiding, +but can result in having to spill some register state to memory. + +Clang supports the ``__attribute__((amdgpu_waves_per_eu(<min>[, <max>])))`` +attribute for the AMDGPU target. This attribute may be attached to a kernel +function definition and is an optimization hint. + +``<min>`` parameter specifies the requested minimum number of waves per EU, and +*optional* ``<max>`` parameter specifies the requested maximum number of waves +per EU (must be greater than ``<min>`` if specified). If ``<max>`` is omitted, +then there is no restriction on the maximum number of waves per EU other than +the one dictated by the hardware for which the kernel is compiled. Passing +``0, 0`` as ``<min>, <max>`` implies the default behavior (no limits). + +If specified, this attribute allows an advanced developer to tune the number of +wavefronts that are capable of fitting within the resources of an EU. The AMDGPU +target backend can use this information to limit resources, such as number of +SGPRs, number of VGPRs, size of available group and private memory segments, in +such a way that guarantees that at least ``<min>`` wavefronts and at most +``<max>`` wavefronts are able to fit within the resources of an EU. Requesting +more wavefronts can hide memory latency but limits available registers which +can result in spilling. Requesting fewer wavefronts can help reduce cache +thrashing, but can reduce memory latency hiding. + +This attribute controls the machine code generated by the AMDGPU target backend +to ensure it is capable of meeting the requested values. However, when the +kernel is executed, there may be other reasons that prevent meeting the request, +for example, there may be wavefronts from other kernels executing on the EU. + +An error will be given if: + - Specified values violate subtarget specifications; + - Specified values are not compatible with values provided through other + attributes; + - The AMDGPU target backend is unable to create machine code that can meet the + request. + + +Calling Conventions +=================== +Clang supports several different calling conventions, depending on the target +platform and architecture. The calling convention used for a function determines +how parameters are passed, how results are returned to the caller, and other +low-level details of calling a function. + +fastcall (gnu::fastcall, __fastcall, _fastcall) +----------------------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","X","","X", "" + +On 32-bit x86 targets, this attribute changes the calling convention of a +function to use ECX and EDX as register parameters and clear parameters off of +the stack on return. This convention does not support variadic calls or +unprototyped functions in C, and has no effect on x86_64 targets. This calling +convention is supported primarily for compatibility with existing code. Users +seeking register parameters should use the ``regparm`` attribute, which does +not require callee-cleanup. See the documentation for `__fastcall`_ on MSDN. + +.. _`__fastcall`: http://msdn.microsoft.com/en-us/library/6xa169sk.aspx + + +ms_abi (gnu::ms_abi) +-------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","X","","", "" + +On non-Windows x86_64 targets, this attribute changes the calling convention of +a function to match the default convention used on Windows x86_64. This +attribute has no effect on Windows targets or non-x86_64 targets. + + +pcs (gnu::pcs) +-------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","X","","", "" + +On ARM targets, this attribute can be used to select calling conventions +similar to ``stdcall`` on x86. Valid parameter values are "aapcs" and +"aapcs-vfp". + + +preserve_all +------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","","","", "" + +On X86-64 and AArch64 targets, this attribute changes the calling convention of +a function. The ``preserve_all`` calling convention attempts to make the code +in the caller even less intrusive than the ``preserve_most`` calling convention. +This calling convention also behaves identical to the ``C`` calling convention +on how arguments and return values are passed, but it uses a different set of +caller/callee-saved registers. This removes the burden of saving and +recovering a large register set before and after the call in the caller. If +the arguments are passed in callee-saved registers, then they will be +preserved by the callee across the call. This doesn't apply for values +returned in callee-saved registers. + +- On X86-64 the callee preserves all general purpose registers, except for + R11. R11 can be used as a scratch register. Furthermore it also preserves + all floating-point registers (XMMs/YMMs). + +The idea behind this convention is to support calls to runtime functions +that don't need to call out to any other functions. + +This calling convention, like the ``preserve_most`` calling convention, will be +used by a future version of the Objective-C runtime and should be considered +experimental at this time. + + +preserve_most +------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","","","", "" + +On X86-64 and AArch64 targets, this attribute changes the calling convention of +a function. The ``preserve_most`` calling convention attempts to make the code +in the caller as unintrusive as possible. This convention behaves identically +to the ``C`` calling convention on how arguments and return values are passed, +but it uses a different set of caller/callee-saved registers. This alleviates +the burden of saving and recovering a large register set before and after the +call in the caller. If the arguments are passed in callee-saved registers, +then they will be preserved by the callee across the call. This doesn't +apply for values returned in callee-saved registers. + +- On X86-64 the callee preserves all general purpose registers, except for + R11. R11 can be used as a scratch register. Floating-point registers + (XMMs/YMMs) are not preserved and need to be saved by the caller. + +The idea behind this convention is to support calls to runtime functions +that have a hot path and a cold path. The hot path is usually a small piece +of code that doesn't use many registers. The cold path might need to call out to +another function and therefore only needs to preserve the caller-saved +registers, which haven't already been saved by the caller. The +`preserve_most` calling convention is very similar to the ``cold`` calling +convention in terms of caller/callee-saved registers, but they are used for +different types of function calls. ``coldcc`` is for function calls that are +rarely executed, whereas `preserve_most` function calls are intended to be +on the hot path and definitely executed a lot. Furthermore ``preserve_most`` +doesn't prevent the inliner from inlining the function call. + +This calling convention will be used by a future version of the Objective-C +runtime and should therefore still be considered experimental at this time. +Although this convention was created to optimize certain runtime calls to +the Objective-C runtime, it is not limited to this runtime and might be used +by other runtimes in the future too. The current implementation only +supports X86-64 and AArch64, but the intention is to support more architectures +in the future. + + +regcall (gnu::regcall, __regcall) +--------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","X","","X", "" + +On x86 targets, this attribute changes the calling convention to +`__regcall`_ convention. This convention aims to pass as many arguments +as possible in registers. It also tries to utilize registers for the +return value whenever it is possible. + +.. _`__regcall`: https://software.intel.com/en-us/node/693069 + + +regparm (gnu::regparm) +---------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","X","","", "" + +On 32-bit x86 targets, the regparm attribute causes the compiler to pass +the first three integer parameters in EAX, EDX, and ECX instead of on the +stack. This attribute has no effect on variadic functions, and all parameters +are passed via the stack as normal. + + +stdcall (gnu::stdcall, __stdcall, _stdcall) +------------------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","X","","X", "" + +On 32-bit x86 targets, this attribute changes the calling convention of a +function to clear parameters off of the stack on return. This convention does +not support variadic calls or unprototyped functions in C, and has no effect on +x86_64 targets. This calling convention is used widely by the Windows API and +COM applications. See the documentation for `__stdcall`_ on MSDN. + +.. _`__stdcall`: http://msdn.microsoft.com/en-us/library/zxk0tw93.aspx + + +thiscall (gnu::thiscall, __thiscall, _thiscall) +----------------------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","X","","X", "" + +On 32-bit x86 targets, this attribute changes the calling convention of a +function to use ECX for the first parameter (typically the implicit ``this`` +parameter of C++ methods) and clear parameters off of the stack on return. This +convention does not support variadic calls or unprototyped functions in C, and +has no effect on x86_64 targets. See the documentation for `__thiscall`_ on +MSDN. + +.. _`__thiscall`: http://msdn.microsoft.com/en-us/library/ek8tkfbw.aspx + + +vectorcall (__vectorcall, _vectorcall) +-------------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","","","X", "" + +On 32-bit x86 *and* x86_64 targets, this attribute changes the calling +convention of a function to pass vector parameters in SSE registers. + +On 32-bit x86 targets, this calling convention is similar to ``__fastcall``. +The first two integer parameters are passed in ECX and EDX. Subsequent integer +parameters are passed in memory, and callee clears the stack. On x86_64 +targets, the callee does *not* clear the stack, and integer parameters are +passed in RCX, RDX, R8, and R9 as is done for the default Windows x64 calling +convention. + +On both 32-bit x86 and x86_64 targets, vector and floating point arguments are +passed in XMM0-XMM5. Homogeneous vector aggregates of up to four elements are +passed in sequential SSE registers if enough are available. If AVX is enabled, +256 bit vectors are passed in YMM0-YMM5. Any vector or aggregate type that +cannot be passed in registers for any reason is passed by reference, which +allows the caller to align the parameter memory. + +See the documentation for `__vectorcall`_ on MSDN for more details. + +.. _`__vectorcall`: http://msdn.microsoft.com/en-us/library/dn375768.aspx + + +Consumed Annotation Checking +============================ +Clang supports additional attributes for checking basic resource management +properties, specifically for unique objects that have a single owning reference. +The following attributes are currently supported, although **the implementation +for these annotations is currently in development and are subject to change.** + +callable_when +------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","","","", "" + +Use ``__attribute__((callable_when(...)))`` to indicate what states a method +may be called in. Valid states are unconsumed, consumed, or unknown. Each +argument to this attribute must be a quoted string. E.g.: + +``__attribute__((callable_when("unconsumed", "unknown")))`` + + +consumable +---------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","","","", "" + +Each ``class`` that uses any of the typestate annotations must first be marked +using the ``consumable`` attribute. Failure to do so will result in a warning. + +This attribute accepts a single parameter that must be one of the following: +``unknown``, ``consumed``, or ``unconsumed``. + + +param_typestate +--------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","","","", "" + +This attribute specifies expectations about function parameters. Calls to an +function with annotated parameters will issue a warning if the corresponding +argument isn't in the expected state. The attribute is also used to set the +initial state of the parameter when analyzing the function's body. + + +return_typestate +---------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","","","", "" + +The ``return_typestate`` attribute can be applied to functions or parameters. +When applied to a function the attribute specifies the state of the returned +value. The function's body is checked to ensure that it always returns a value +in the specified state. On the caller side, values returned by the annotated +function are initialized to the given state. + +When applied to a function parameter it modifies the state of an argument after +a call to the function returns. The function's body is checked to ensure that +the parameter is in the expected state before returning. + + +set_typestate +------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","","","", "" + +Annotate methods that transition an object into a new state with +``__attribute__((set_typestate(new_state)))``. The new state must be +unconsumed, consumed, or unknown. + + +test_typestate +-------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","","","", "" + +Use ``__attribute__((test_typestate(tested_state)))`` to indicate that a method +returns true if the object is in the specified state.. + + +OpenCL Address Spaces +===================== +The address space qualifier may be used to specify the region of memory that is +used to allocate the object. OpenCL supports the following address spaces: +__generic(generic), __global(global), __local(local), __private(private), +__constant(constant). + + .. code-block:: c + + __constant int c = ...; + + __generic int* foo(global int* g) { + __local int* l; + private int p; + ... + return l; + } + +More details can be found in the OpenCL C language Spec v2.0, Section 6.5. + +constant (__constant) +--------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "","","","X", "" + +The constant address space attribute signals that an object is located in +a constant (non-modifiable) memory region. It is available to all work items. +Any type can be annotated with the constant address space attribute. Objects +with the constant address space qualifier can be declared in any scope and must +have an initializer. + + +generic (__generic) +------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "","","","X", "" + +The generic address space attribute is only available with OpenCL v2.0 and later. +It can be used with pointer types. Variables in global and local scope and +function parameters in non-kernel functions can have the generic address space +type attribute. It is intended to be a placeholder for any other address space +except for '__constant' in OpenCL code which can be used with multiple address +spaces. + + +global (__global) +----------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "","","","X", "" + +The global address space attribute specifies that an object is allocated in +global memory, which is accessible by all work items. The content stored in this +memory area persists between kernel executions. Pointer types to the global +address space are allowed as function parameters or local variables. Starting +with OpenCL v2.0, the global address space can be used with global (program +scope) variables and static local variable as well. + + +local (__local) +--------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "","","","X", "" + +The local address space specifies that an object is allocated in the local (work +group) memory area, which is accessible to all work items in the same work +group. The content stored in this memory region is not accessible after +the kernel execution ends. In a kernel function scope, any variable can be in +the local address space. In other scopes, only pointer types to the local address +space are allowed. Local address space variables cannot have an initializer. + + +private (__private) +------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "","","","X", "" + +The private address space specifies that an object is allocated in the private +(work item) memory. Other work items cannot access the same memory area and its +content is destroyed after work item execution ends. Local variables can be +declared in the private address space. Function arguments are always in the +private address space. Kernel function arguments of a pointer or an array type +cannot point to the private address space. + + +Nullability Attributes +====================== +Whether a particular pointer may be "null" is an important concern when working with pointers in the C family of languages. The various nullability attributes indicate whether a particular pointer can be null or not, which makes APIs more expressive and can help static analysis tools identify bugs involving null pointers. Clang supports several kinds of nullability attributes: the ``nonnull`` and ``returns_nonnull`` attributes indicate which function or method parameters and result types can never be null, while nullability type qualifiers indicate which pointer types can be null (``_Nullable``) or cannot be null (``_Nonnull``). + +The nullability (type) qualifiers express whether a value of a given pointer type can be null (the ``_Nullable`` qualifier), doesn't have a defined meaning for null (the ``_Nonnull`` qualifier), or for which the purpose of null is unclear (the ``_Null_unspecified`` qualifier). Because nullability qualifiers are expressed within the type system, they are more general than the ``nonnull`` and ``returns_nonnull`` attributes, allowing one to express (for example) a nullable pointer to an array of nonnull pointers. Nullability qualifiers are written to the right of the pointer to which they apply. For example: + + .. code-block:: c + + // No meaningful result when 'ptr' is null (here, it happens to be undefined behavior). + int fetch(int * _Nonnull ptr) { return *ptr; } + + // 'ptr' may be null. + int fetch_or_zero(int * _Nullable ptr) { + return ptr ? *ptr : 0; + } + + // A nullable pointer to non-null pointers to const characters. + const char *join_strings(const char * _Nonnull * _Nullable strings, unsigned n); + +In Objective-C, there is an alternate spelling for the nullability qualifiers that can be used in Objective-C methods and properties using context-sensitive, non-underscored keywords. For example: + + .. code-block:: objective-c + + @interface NSView : NSResponder + - (nullable NSView *)ancestorSharedWithView:(nonnull NSView *)aView; + @property (assign, nullable) NSView *superview; + @property (readonly, nonnull) NSArray *subviews; + @end + +nonnull (gnu::nonnull) +---------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","X","","", "" + +The ``nonnull`` attribute indicates that some function parameters must not be null, and can be used in several different ways. It's original usage (`from GCC <https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes>`_) is as a function (or Objective-C method) attribute that specifies which parameters of the function are nonnull in a comma-separated list. For example: + + .. code-block:: c + + extern void * my_memcpy (void *dest, const void *src, size_t len) + __attribute__((nonnull (1, 2))); + +Here, the ``nonnull`` attribute indicates that parameters 1 and 2 +cannot have a null value. Omitting the parenthesized list of parameter indices means that all parameters of pointer type cannot be null: + + .. code-block:: c + + extern void * my_memcpy (void *dest, const void *src, size_t len) + __attribute__((nonnull)); + +Clang also allows the ``nonnull`` attribute to be placed directly on a function (or Objective-C method) parameter, eliminating the need to specify the parameter index ahead of type. For example: + + .. code-block:: c + + extern void * my_memcpy (void *dest __attribute__((nonnull)), + const void *src __attribute__((nonnull)), size_t len); + +Note that the ``nonnull`` attribute indicates that passing null to a non-null parameter is undefined behavior, which the optimizer may take advantage of to, e.g., remove null checks. The ``_Nonnull`` type qualifier indicates that a pointer cannot be null in a more general manner (because it is part of the type system) and does not imply undefined behavior, making it more widely applicable. + + +returns_nonnull (gnu::returns_nonnull) +-------------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "X","X","","", "" + +The ``returns_nonnull`` attribute indicates that a particular function (or Objective-C method) always returns a non-null pointer. For example, a particular system ``malloc`` might be defined to terminate a process when memory is not available rather than returning a null pointer: + + .. code-block:: c + + extern void * malloc (size_t size) __attribute__((returns_nonnull)); + +The ``returns_nonnull`` attribute implies that returning a null pointer is undefined behavior, which the optimizer may take advantage of. The ``_Nonnull`` type qualifier indicates that a pointer cannot be null in a more general manner (because it is part of the type system) and does not imply undefined behavior, making it more widely applicable + + +_Nonnull +-------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "","","","X", "" + +The ``_Nonnull`` nullability qualifier indicates that null is not a meaningful value for a value of the ``_Nonnull`` pointer type. For example, given a declaration such as: + + .. code-block:: c + + int fetch(int * _Nonnull ptr); + +a caller of ``fetch`` should not provide a null value, and the compiler will produce a warning if it sees a literal null value passed to ``fetch``. Note that, unlike the declaration attribute ``nonnull``, the presence of ``_Nonnull`` does not imply that passing null is undefined behavior: ``fetch`` is free to consider null undefined behavior or (perhaps for backward-compatibility reasons) defensively handle null. + + +_Null_unspecified +----------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "","","","X", "" + +The ``_Null_unspecified`` nullability qualifier indicates that neither the ``_Nonnull`` nor ``_Nullable`` qualifiers make sense for a particular pointer type. It is used primarily to indicate that the role of null with specific pointers in a nullability-annotated header is unclear, e.g., due to overly-complex implementations or historical factors with a long-lived API. + + +_Nullable +--------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma" + + "","","","X", "" + +The ``_Nullable`` nullability qualifier indicates that a value of the ``_Nullable`` pointer type can be null. For example, given: + + .. code-block:: c + + int fetch_or_zero(int * _Nullable ptr); + +a caller of ``fetch_or_zero`` can provide null. + + diff --git a/docs/ReleaseNotes.rst b/docs/ReleaseNotes.rst index b15d9a5a147c..5b035cd3320f 100644 --- a/docs/ReleaseNotes.rst +++ b/docs/ReleaseNotes.rst @@ -31,11 +31,6 @@ the latest release, please check out the main please see the `Clang Web Site <http://clang.llvm.org>`_ or the `LLVM Web Site <http://llvm.org>`_. -Note that if you are reading this file from a Subversion checkout or the -main Clang web page, this document applies to the *next* release, not -the current one. To see the release notes for a specific release, please -see the `releases page <http://llvm.org/releases/>`_. - What's New in Clang 4.0.0? ========================== @@ -65,6 +60,8 @@ The option -Og has been added to optimize the debugging experience. For now, this option is exactly the same as -O1. However, in the future, some other optimizations might be enabled or disabled. +The option -MJ has been added to simplify adding JSON compilation +database output into existing build systems. The option .... diff --git a/docs/UsersManual.rst b/docs/UsersManual.rst index 96b7ac95cb5d..3adbfe059f89 100644 --- a/docs/UsersManual.rst +++ b/docs/UsersManual.rst @@ -41,6 +41,7 @@ specific section: variants depending on base language. - :ref:`C++ Language <cxx>` - :ref:`Objective C++ Language <objcxx>` +- :ref:`OpenCL C Language <opencl>`: v1.0, v1.1, v1.2, v2.0. In addition to these base languages and their dialects, Clang supports a broad variety of language extensions, which are documented in the @@ -1973,6 +1974,365 @@ Controlling implementation limits is provided or target does not support TLS, code generation for threadprivate variables relies on OpenMP runtime library. +.. _opencl: + +OpenCL Features +=============== + +Clang can be used to compile OpenCL kernels for execution on a device +(e.g. GPU). It is possible to compile the kernel into a binary (e.g. for AMD or +Nvidia targets) that can be uploaded to run directly on a device (e.g. using +`clCreateProgramWithBinary +<https://www.khronos.org/registry/OpenCL/specs/opencl-1.1.pdf#111>`_) or +into generic bitcode files loadable into other toolchains. + +Compiling to a binary using the default target from the installation can be done +as follows: + + .. code-block:: console + + $ echo "kernel void k(){}" > test.cl + $ clang test.cl + +Compiling for a specific target can be done by specifying the triple corresponding +to the target, for example: + + .. code-block:: console + + $ clang -target nvptx64-unknown-unknown test.cl + $ clang -target amdgcn-amd-amdhsa-opencl test.cl + +Compiling to bitcode can be done as follows: + + .. code-block:: console + + $ clang -c -emit-llvm test.cl + +This will produce a generic test.bc file that can be used in vendor toolchains +to perform machine code generation. + +Clang currently supports OpenCL C language standards up to v2.0. + +OpenCL Specific Options +----------------------- + +Most of the OpenCL build options from `the specification v2.0 section 5.8.4 +<https://www.khronos.org/registry/cl/specs/opencl-2.0.pdf#200>`_ are available. + +Examples: + + .. code-block:: console + + $ clang -cl-std=CL2.0 -cl-single-precision-constant test.cl + +Some extra options are available to support special OpenCL features. + +.. option:: -finclude-default-header + +Loads standard includes during compilations. By default OpenCL headers are not +loaded and therefore standard library includes are not available. To load them +automatically a flag has been added to the frontend (see also :ref:`the section +on the OpenCL Header <opencl_header>`): + + .. code-block:: console + + $ clang -Xclang -finclude-default-header test.cl + +Alternatively ``-include`` or ``-I`` followed by the path to the header location +can be given manually. + + .. code-block:: console + + $ clang -I<path to clang>/lib/Headers/opencl-c.h test.cl + +In this case the kernel code should contain ``#include <opencl-c.h>`` just as a +regular C include. + +.. option:: -cl-ext + +Disables support of OpenCL extensions. All OpenCL targets provide a list +of extensions that they support. Clang allows to amend this using the ``-cl-ext`` +flag with a comma-separated list of extensions prefixed with ``'+'`` or ``'-'``. +The syntax: ``-cl-ext=<(['-'|'+']<extension>[,])+>``, where extensions +can be either one of `the OpenCL specification extensions +<https://www.khronos.org/registry/cl/sdk/2.0/docs/man/xhtml/EXTENSION.html>`_ +or any known vendor extension. Alternatively, ``'all'`` can be used to enable +or disable all known extensions. +Example disabling double support for the 64-bit SPIR target: + + .. code-block:: console + + $ clang -cc1 -triple spir64-unknown-unknown -cl-ext=-cl_khr_fp64 test.cl + +Enabling all extensions except double support in R600 AMD GPU can be done using: + + .. code-block:: console + + $ clang -cc1 -triple r600-unknown-unknown -cl-ext=-all,+cl_khr_fp16 test.cl + +.. _opencl_fake_address_space_map: + +.. option:: -ffake-address-space-map + +Overrides the target address space map with a fake map. +This allows adding explicit address space IDs to the bitcode for non-segmented +memory architectures that don't have separate IDs for each of the OpenCL +logical address spaces by default. Passing ``-ffake-address-space-map`` will +add/override address spaces of the target compiled for with the following values: +``1-global``, ``2-constant``, ``3-local``, ``4-generic``. The private address +space is represented by the absence of an address space attribute in the IR (see +also :ref:`the section on the address space attribute <opencl_addrsp>`). + + .. code-block:: console + + $ clang -ffake-address-space-map test.cl + +Some other flags used for the compilation for C can also be passed while +compiling for OpenCL, examples: ``-c``, ``-O<1-4|s>``, ``-o``, ``-emit-llvm``, etc. + +OpenCL Targets +-------------- + +OpenCL targets are derived from the regular Clang target classes. The OpenCL +specific parts of the target representation provide address space mapping as +well as a set of supported extensions. + +Specific Targets +^^^^^^^^^^^^^^^^ + +There is a set of concrete HW architectures that OpenCL can be compiled for. + +- For AMD target: + + .. code-block:: console + + $ clang -target amdgcn-amd-amdhsa-opencl test.cl + +- For Nvidia architectures: + + .. code-block:: console + + $ clang -target nvptx64-unknown-unknown test.cl + + +Generic Targets +^^^^^^^^^^^^^^^ + +- SPIR is available as a generic target to allow portable bitcode to be produced + that can be used across GPU toolchains. The implementation follows `the SPIR + specification <https://www.khronos.org/spir>`_. There are two flavors + available for 32 and 64 bits. + + .. code-block:: console + + $ clang -target spir-unknown-unknown test.cl + $ clang -target spir64-unknown-unknown test.cl + + All known OpenCL extensions are supported in the SPIR targets. Clang will + generate SPIR v1.2 compatible IR for OpenCL versions up to 2.0 and SPIR v2.0 + for OpenCL v2.0. + +- x86 is used by some implementations that are x86 compatible and currently + remains for backwards compatibility (with older implementations prior to + SPIR target support). For "non-SPMD" targets which cannot spawn multiple + work-items on the fly using hardware, which covers practically all non-GPU + devices such as CPUs and DSPs, additional processing is needed for the kernels + to support multiple work-item execution. For this, a 3rd party toolchain, + such as for example `POCL <http://portablecl.org/>`_, can be used. + + This target does not support multiple memory segments and, therefore, the fake + address space map can be added using the :ref:`-ffake-address-space-map + <opencl_fake_address_space_map>` flag. + +.. _opencl_header: + +OpenCL Header +------------- + +By default Clang will not include standard headers and therefore OpenCL builtin +functions and some types (i.e. vectors) are unknown. The default CL header is, +however, provided in the Clang installation and can be enabled by passing the +``-finclude-default-header`` flag to the Clang frontend. + + .. code-block:: console + + $ echo "bool is_wg_uniform(int i){return get_enqueued_local_size(i)==get_local_size(i);}" > test.cl + $ clang -Xclang -finclude-default-header -cl-std=CL2.0 test.cl + +Because the header is very large and long to parse, PCH (:doc:`PCHInternals`) +and modules (:doc:`Modules`) are used internally to improve the compilation +speed. + +To enable modules for OpenCL: + + .. code-block:: console + + $ clang -target spir-unknown-unknown -c -emit-llvm -Xclang -finclude-default-header -fmodules -fimplicit-module-maps -fmodules-cache-path=<path to the generated module> test.cl + +OpenCL Metadata +--------------- + +Clang uses metadata to provide additional OpenCL semantics in IR needed for +backends and OpenCL runtime. + +Each kernel will have function metadata attached to it, specifying the arguments. +Kernel argument metadata is used to provide source level information for querying +at runtime, for example using the `clGetKernelArgInfo +<https://www.khronos.org/registry/OpenCL/specs/opencl-1.2.pdf#167>`_ +call. + +Note that ``-cl-kernel-arg-info`` enables more information about the original CL +code to be added e.g. kernel parameter names will appear in the OpenCL metadata +along with other information. + +The IDs used to encode the OpenCL's logical address spaces in the argument info +metadata follows the SPIR address space mapping as defined in the SPIR +specification `section 2.2 +<https://www.khronos.org/registry/spir/specs/spir_spec-2.0.pdf#18>`_ + +OpenCL-Specific Attributes +-------------------------- + +OpenCL support in Clang contains a set of attribute taken directly from the +specification as well as additional attributes. + +See also :doc:`AttributeReference`. + +nosvm +^^^^^ + +Clang supports this attribute to comply to OpenCL v2.0 conformance, but it +does not have any effect on the IR. For more details reffer to the specification +`section 6.7.2 +<https://www.khronos.org/registry/cl/specs/opencl-2.0-openclc.pdf#49>`_ + + +opencl_hint_unroll +^^^^^^^^^^^^^^^^^^ + +The implementation of this feature mirrors the unroll hint for C. +More details on the syntax can be found in the specification +`section 6.11.5 +<https://www.khronos.org/registry/cl/specs/opencl-2.0-openclc.pdf#61>`_ + +convergent +^^^^^^^^^^ + +To make sure no invalid optimizations occur for single program multiple data +(SPMD) / single instruction multiple thread (SIMT) Clang provides attributes that +can be used for special functions that have cross work item semantics. +An example is the subgroup operations such as `intel_sub_group_shuffle +<https://www.khronos.org/registry/cl/extensions/intel/cl_intel_subgroups.txt>`_ + + .. code-block:: c + + // Define custom my_sub_group_shuffle(data, c) + // that makes use of intel_sub_group_shuffle + r1 = … + if (r0) r1 = computeA(); + // Shuffle data from r1 into r3 + // of threads id r2. + r3 = my_sub_group_shuffle(r1, r2); + if (r0) r3 = computeB(); + +with non-SPMD semantics this is optimized to the following equivalent code: + + .. code-block:: c + + r1 = … + if (!r0) + // Incorrect functionality! The data in r1 + // have not been computed by all threads yet. + r3 = my_sub_group_shuffle(r1, r2); + else { + r1 = computeA(); + r3 = my_sub_group_shuffle(r1, r2); + r3 = computeB(); + } + +Declaring the function ``my_sub_group_shuffle`` with the convergent attribute +would prevent this: + + .. code-block:: c + + my_sub_group_shuffle() __attribute__((convergent)); + +Using ``convergent`` guarantees correct execution by keeping CFG equivalence +wrt operations marked as ``convergent``. CFG ``G´`` is equivalent to ``G`` wrt +node ``Ni`` : ``iff ∀ Nj (i≠j)`` domination and post-domination relations with +respect to ``Ni`` remain the same in both ``G`` and ``G´``. + +noduplicate +^^^^^^^^^^^ + +``noduplicate`` is more restrictive with respect to optimizations than +``convergent`` because a convergent function only preserves CFG equivalence. +This allows some optimizations to happen as long as the control flow remains +unmodified. + + .. code-block:: c + + for (int i=0; i<4; i++) + my_sub_group_shuffle() + +can be modified to: + + .. code-block:: c + + my_sub_group_shuffle(); + my_sub_group_shuffle(); + my_sub_group_shuffle(); + my_sub_group_shuffle(); + +while using ``noduplicate`` would disallow this. Also ``noduplicate`` doesn't +have the same safe semantics of CFG as ``convergent`` and can cause changes in +CFG that modify semantics of the original program. + +``noduplicate`` is kept for backwards compatibility only and it considered to be +deprecated for future uses. + +.. _opencl_addrsp: + +address_space +^^^^^^^^^^^^^ + +Clang has arbitrary address space support using the ``address_space(N)`` +attribute, where ``N`` is an integer number in the range ``0`` to ``16777215`` +(``0xffffffu``). + +An OpenCL implementation provides a list of standard address spaces using +keywords: ``private``, ``local``, ``global``, and ``generic``. In the AST and +in the IR local, global, or generic will be represented by the address space +attribute with the corresponding unique number. Note that private does not have +any corresponding attribute added and, therefore, is represented by the absence +of an address space number. The specific IDs for an address space do not have to +match between the AST and the IR. Typically in the AST address space numbers +represent logical segments while in the IR they represent physical segments. +Therefore, machines with flat memory segments can map all AST address space +numbers to the same physical segment ID or skip address space attribute +completely while generating the IR. However, if the address space information +is needed by the IR passes e.g. to improve alias analysis, it is recommended +to keep it and only lower to reflect physical memory segments in the late +machine passes. + +OpenCL builtins +--------------- + +There are some standard OpenCL functions that are implemented as Clang builtins: + +- All pipe functions from `section 6.13.16.2/6.13.16.3 + <https://www.khronos.org/registry/cl/specs/opencl-2.0-openclc.pdf#160>`_ of + the OpenCL v2.0 kernel language specification. ` + +- Address space qualifier conversion functions ``to_global``/``to_local``/``to_private`` + from `section 6.13.9 + <https://www.khronos.org/registry/cl/specs/opencl-2.0-openclc.pdf#101>`_. + +- All the ``enqueue_kernel`` functions from `section 6.13.17.1 + <https://www.khronos.org/registry/cl/specs/opencl-2.0-openclc.pdf#164>`_ and + enqueue query functions from `section 6.13.17.5 + <https://www.khronos.org/registry/cl/specs/opencl-2.0-openclc.pdf#171>`_. + .. _target_features: Target-Specific Features and Limitations @@ -2102,7 +2462,7 @@ Clang expects the GCC executable "gcc.exe" compiled for clang-cl ======== -clang-cl is an alternative command-line interface to Clang driver, designed for +clang-cl is an alternative command-line interface to Clang, designed for compatibility with the Visual C++ compiler, cl.exe. To enable clang-cl to find system headers, libraries, and the linker when run @@ -2110,7 +2470,7 @@ from the command-line, it should be executed inside a Visual Studio Native Tools Command Prompt or a regular Command Prompt where the environment has been set up using e.g. `vcvars32.bat <http://msdn.microsoft.com/en-us/library/f2ccy3wt.aspx>`_. -clang-cl can also be used from inside Visual Studio by using an LLVM Platform +clang-cl can also be used from inside Visual Studio by using an LLVM Platform Toolset. Command-Line Options @@ -2145,116 +2505,125 @@ Execute ``clang-cl /?`` to see a list of supported options: :: CL.EXE COMPATIBILITY OPTIONS: - /? Display available options - /arch:<value> Set architecture for code generation - /Brepro- Emit an object file which cannot be reproduced over time - /Brepro Emit an object file which can be reproduced over time - /C Don't discard comments when preprocessing - /c Compile only - /D <macro[=value]> Define macro - /EH<value> Exception handling model - /EP Disable linemarker output and preprocess to stdout - /E Preprocess to stdout - /fallback Fall back to cl.exe if clang-cl fails to compile - /FA Output assembly code file during compilation - /Fa<file or directory> Output assembly code to this file during compilation (with /FA) - /Fe<file or directory> Set output executable file or directory (ends in / or \) - /FI <value> Include file before parsing - /Fi<file> Set preprocess output file name (with /P) - /Fo<file or directory> Set output object file, or directory (ends in / or \) (with /c) + /? Display available options + /arch:<value> Set architecture for code generation + /Brepro- Emit an object file which cannot be reproduced over time + /Brepro Emit an object file which can be reproduced over time + /C Don't discard comments when preprocessing + /c Compile only + /D <macro[=value]> Define macro + /EH<value> Exception handling model + /EP Disable linemarker output and preprocess to stdout + /execution-charset:<value> + Runtime encoding, supports only UTF-8 + /E Preprocess to stdout + /fallback Fall back to cl.exe if clang-cl fails to compile + /FA Output assembly code file during compilation + /Fa<file or directory> Output assembly code to this file during compilation (with /FA) + /Fe<file or directory> Set output executable file or directory (ends in / or \) + /FI <value> Include file before parsing + /Fi<file> Set preprocess output file name (with /P) + /Fo<file or directory> Set output object file, or directory (ends in / or \) (with /c) /fp:except- /fp:except /fp:fast /fp:precise /fp:strict - /Fp<filename> Set pch filename (with /Yc and /Yu) - /GA Assume thread-local variables are defined in the executable - /Gd Set __cdecl as a default calling convention - /GF- Disable string pooling - /GR- Disable emission of RTTI data - /GR Enable emission of RTTI data - /Gr Set __fastcall as a default calling convention - /GS- Disable buffer security check - /GS Enable buffer security check - /Gs<value> Set stack probe size - /Gv Set __vectorcall as a default calling convention - /Gw- Don't put each data item in its own section - /Gw Put each data item in its own section - /GX- Enable exception handling - /GX Enable exception handling - /Gy- Don't put each function in its own section - /Gy Put each function in its own section - /Gz Set __stdcall as a default calling convention - /help Display available options - /imsvc <dir> Add directory to system include search path, as if part of %INCLUDE% - /I <dir> Add directory to include search path - /J Make char type unsigned - /LDd Create debug DLL - /LD Create DLL - /link <options> Forward options to the linker - /MDd Use DLL debug run-time - /MD Use DLL run-time - /MTd Use static debug run-time - /MT Use static run-time - /Od Disable optimization - /Oi- Disable use of builtin functions - /Oi Enable use of builtin functions - /Os Optimize for size - /Ot Optimize for speed - /O<value> Optimization level - /o <file or directory> Set output file or directory (ends in / or \) - /P Preprocess to file - /Qvec- Disable the loop vectorization passes - /Qvec Enable the loop vectorization passes - /showIncludes Print info about included files to stderr - /std:<value> Language standard to compile for - /TC Treat all source files as C - /Tc <filename> Specify a C source file - /TP Treat all source files as C++ - /Tp <filename> Specify a C++ source file - /U <macro> Undefine macro - /vd<value> Control vtordisp placement - /vmb Use a best-case representation method for member pointers - /vmg Use a most-general representation for member pointers - /vmm Set the default most-general representation to multiple inheritance - /vms Set the default most-general representation to single inheritance - /vmv Set the default most-general representation to virtual inheritance - /volatile:iso Volatile loads and stores have standard semantics - /volatile:ms Volatile loads and stores have acquire and release semantics - /W0 Disable all warnings - /W1 Enable -Wall - /W2 Enable -Wall - /W3 Enable -Wall - /W4 Enable -Wall and -Wextra - /Wall Enable -Wall and -Wextra - /WX- Do not treat warnings as errors - /WX Treat warnings as errors - /w Disable all warnings - /Y- Disable precompiled headers, overrides /Yc and /Yu - /Yc<filename> Generate a pch file for all code up to and including <filename> - /Yu<filename> Load a pch file and use it instead of all code up to and including <filename> - /Z7 Enable CodeView debug information in object files - /Zc:sizedDealloc- Disable C++14 sized global deallocation functions - /Zc:sizedDealloc Enable C++14 sized global deallocation functions - /Zc:strictStrings Treat string literals as const - /Zc:threadSafeInit- Disable thread-safe initialization of static variables - /Zc:threadSafeInit Enable thread-safe initialization of static variables - /Zc:trigraphs- Disable trigraphs (default) - /Zc:trigraphs Enable trigraphs - /Zd Emit debug line number tables only - /Zi Alias for /Z7. Does not produce PDBs. - /Zl Don't mention any default libraries in the object file - /Zp Set the default maximum struct packing alignment to 1 - /Zp<value> Specify the default maximum struct packing alignment - /Zs Syntax-check only + /Fp<filename> Set pch filename (with /Yc and /Yu) + /GA Assume thread-local variables are defined in the executable + /Gd Set __cdecl as a default calling convention + /GF- Disable string pooling + /GR- Disable emission of RTTI data + /GR Enable emission of RTTI data + /Gr Set __fastcall as a default calling convention + /GS- Disable buffer security check + /GS Enable buffer security check + /Gs<value> Set stack probe size + /Gv Set __vectorcall as a default calling convention + /Gw- Don't put each data item in its own section + /Gw Put each data item in its own section + /GX- Enable exception handling + /GX Enable exception handling + /Gy- Don't put each function in its own section + /Gy Put each function in its own section + /Gz Set __stdcall as a default calling convention + /help Display available options + /imsvc <dir> Add directory to system include search path, as if part of %INCLUDE% + /I <dir> Add directory to include search path + /J Make char type unsigned + /LDd Create debug DLL + /LD Create DLL + /link <options> Forward options to the linker + /MDd Use DLL debug run-time + /MD Use DLL run-time + /MTd Use static debug run-time + /MT Use static run-time + /Od Disable optimization + /Oi- Disable use of builtin functions + /Oi Enable use of builtin functions + /Os Optimize for size + /Ot Optimize for speed + /O<value> Optimization level + /o <file or directory> Set output file or directory (ends in / or \) + /P Preprocess to file + /Qvec- Disable the loop vectorization passes + /Qvec Enable the loop vectorization passes + /showIncludes Print info about included files to stderr + /source-charset:<value> Source encoding, supports only UTF-8 + /std:<value> Language standard to compile for + /TC Treat all source files as C + /Tc <filename> Specify a C source file + /TP Treat all source files as C++ + /Tp <filename> Specify a C++ source file + /utf-8 Set source and runtime encoding to UTF-8 (default) + /U <macro> Undefine macro + /vd<value> Control vtordisp placement + /vmb Use a best-case representation method for member pointers + /vmg Use a most-general representation for member pointers + /vmm Set the default most-general representation to multiple inheritance + /vms Set the default most-general representation to single inheritance + /vmv Set the default most-general representation to virtual inheritance + /volatile:iso Volatile loads and stores have standard semantics + /volatile:ms Volatile loads and stores have acquire and release semantics + /W0 Disable all warnings + /W1 Enable -Wall + /W2 Enable -Wall + /W3 Enable -Wall + /W4 Enable -Wall and -Wextra + /Wall Enable -Wall and -Wextra + /WX- Do not treat warnings as errors + /WX Treat warnings as errors + /w Disable all warnings + /Y- Disable precompiled headers, overrides /Yc and /Yu + /Yc<filename> Generate a pch file for all code up to and including <filename> + /Yu<filename> Load a pch file and use it instead of all code up to and including <filename> + /Z7 Enable CodeView debug information in object files + /Zc:sizedDealloc- Disable C++14 sized global deallocation functions + /Zc:sizedDealloc Enable C++14 sized global deallocation functions + /Zc:strictStrings Treat string literals as const + /Zc:threadSafeInit- Disable thread-safe initialization of static variables + /Zc:threadSafeInit Enable thread-safe initialization of static variables + /Zc:trigraphs- Disable trigraphs (default) + /Zc:trigraphs Enable trigraphs + /Zd Emit debug line number tables only + /Zi Alias for /Z7. Does not produce PDBs. + /Zl Don't mention any default libraries in the object file + /Zp Set the default maximum struct packing alignment to 1 + /Zp<value> Specify the default maximum struct packing alignment + /Zs Syntax-check only OPTIONS: -### Print (but do not run) the commands to run for this compilation --analyze Run the static analyzer -fansi-escape-codes Use ANSI escape codes for diagnostics -fcolor-diagnostics Use colors in diagnostics + -fdelayed-template-parsing + Parse templated function definitions at the end of the translation unit + -fdiagnostics-absolute-paths + Print absolute paths in diagnostics -fdiagnostics-parseable-fixits Print fix-its in machine parseable form + -flto Enable LTO in 'full' mode -fms-compatibility-version=<value> Dot-separated value representing the Microsoft compiler version number to report in _MSC_VER (0 = don't define it (default)) @@ -2262,12 +2631,23 @@ Execute ``clang-cl /?`` to see a list of supported options: -fms-extensions Accept some non-standard constructs supported by the Microsoft compiler -fmsc-version=<value> Microsoft compiler version number to report in _MSC_VER (0 = don't define it (default)) + -fno-delayed-template-parsing + Disable delayed template parsing -fno-sanitize-coverage=<value> Disable specified features of coverage instrumentation for Sanitizers -fno-sanitize-recover=<value> Disable recovery for specified sanitizers -fno-sanitize-trap=<value> Disable trapping for specified sanitizers + -fno-standalone-debug Limit debug information produced to reduce size of debug binary + -fprofile-instr-generate=<file> + Generate instrumented code to collect execution counts into <file> + (overridden by LLVM_PROFILE_FILE env var) + -fprofile-instr-generate + Generate instrumented code to collect execution counts into default.profraw file + (overriden by '=' form of option or LLVM_PROFILE_FILE env var) + -fprofile-instr-use=<value> + Use instrumentation data for profile-guided optimization -fsanitize-blacklist=<value> Path to blacklist file for sanitizers -fsanitize-coverage=<value> @@ -2277,6 +2657,7 @@ Execute ``clang-cl /?`` to see a list of supported options: -fsanitize-trap=<value> Enable trapping for specified sanitizers -fsanitize=<check> Turn on runtime checks for various forms of undefined or suspicious behavior. See user manual for available checks + -fstandalone-debug Emit full debug info for all types used by the program -gcodeview Generate CodeView debug information -gline-tables-only Emit debug line number tables only -miamcu Use Intel MCU ABI diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index e9d9ab03a8b0..15fde19eb974 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -2370,7 +2370,11 @@ enum CXCursorKind { */ CXCursor_OMPTargetTeamsDistributeParallelForSimdDirective = 278, - CXCursor_LastStmt = CXCursor_OMPTargetTeamsDistributeParallelForSimdDirective, + /** \brief OpenMP target teams distribute simd directive. + */ + CXCursor_OMPTargetTeamsDistributeSimdDirective = 279, + + CXCursor_LastStmt = CXCursor_OMPTargetTeamsDistributeSimdDirective, /** * \brief Cursor that represents the translation unit itself. diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index b2e332d6d85c..8b52891af2f8 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -2061,6 +2061,10 @@ public: /// limited representation in the AST. SourceRange getReturnTypeSourceRange() const; + /// \brief Attempt to compute an informative source range covering the + /// function exception specification, if any. + SourceRange getExceptionSpecSourceRange() const; + /// \brief Determine the type of an expression that calls this function. QualType getCallResultType() const { assert(getType()->getAs<FunctionType>() && "Expected a FunctionType!"); diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index 2af95c02c460..dc50a190de42 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -2028,8 +2028,7 @@ public: SourceLocation L, DeclarationName Name, TemplateParameterList *Params, - NamedDecl *Decl, - ClassTemplateDecl *PrevDecl); + NamedDecl *Decl); /// \brief Create an empty class template node. static ClassTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID); diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index cbf0bee69f00..10a930abe6fb 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -2672,6 +2672,9 @@ DEF_TRAVERSE_STMT(OMPTargetTeamsDistributeParallelForDirective, DEF_TRAVERSE_STMT(OMPTargetTeamsDistributeParallelForSimdDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPTargetTeamsDistributeSimdDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + // OpenMP clauses. template <typename Derived> bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) { diff --git a/include/clang/AST/StmtOpenMP.h b/include/clang/AST/StmtOpenMP.h index 61cae7b6d258..ec532ecd5881 100644 --- a/include/clang/AST/StmtOpenMP.h +++ b/include/clang/AST/StmtOpenMP.h @@ -3711,6 +3711,75 @@ public: } }; +/// This represents '#pragma omp target teams distribute simd' combined +/// directive. +/// +/// \code +/// #pragma omp target teams distribute simd private(x) +/// \endcode +/// In this example directive '#pragma omp target teams distribute simd' +/// has clause 'private' with the variables 'x' +/// +class OMPTargetTeamsDistributeSimdDirective final : public OMPLoopDirective { + friend class ASTStmtReader; + + /// Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + OMPTargetTeamsDistributeSimdDirective(SourceLocation StartLoc, + SourceLocation EndLoc, + unsigned CollapsedNum, + unsigned NumClauses) + : OMPLoopDirective(this, OMPTargetTeamsDistributeSimdDirectiveClass, + OMPD_target_teams_distribute_simd, StartLoc, EndLoc, + CollapsedNum, NumClauses) {} + + /// Build an empty directive. + /// + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + explicit OMPTargetTeamsDistributeSimdDirective(unsigned CollapsedNum, + unsigned NumClauses) + : OMPLoopDirective(this, OMPTargetTeamsDistributeSimdDirectiveClass, + OMPD_target_teams_distribute_simd, SourceLocation(), + SourceLocation(), CollapsedNum, NumClauses) {} + +public: + /// Creates directive with a list of \a Clauses. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param CollapsedNum Number of collapsed loops. + /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement, associated with the directive. + /// \param Exprs Helper expressions for CodeGen. + /// + static OMPTargetTeamsDistributeSimdDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt, const HelperExprs &Exprs); + + /// Creates an empty directive with the place for \a NumClauses clauses. + /// + /// \param C AST context. + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + static OMPTargetTeamsDistributeSimdDirective * + CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum, + EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPTargetTeamsDistributeSimdDirectiveClass; + } +}; + } // end namespace clang #endif diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index 7de666838d44..5b7d9e6e3ce1 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -1351,6 +1351,19 @@ class FunctionTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, FunctionTypeLoc, FunctionType, FunctionLocInfo> { + bool hasExceptionSpec() const { + if (auto *FPT = dyn_cast<FunctionProtoType>(getTypePtr())) { + return FPT->hasExceptionSpec(); + } + return false; + } + + SourceRange *getExceptionSpecRangePtr() const { + assert(hasExceptionSpec() && "No exception spec range"); + // After the Info comes the ParmVarDecl array, and after that comes the + // exception specification information. + return (SourceRange *)(getParmArray() + getNumParams()); + } public: SourceLocation getLocalRangeBegin() const { return getLocalData()->LocalRangeBegin; @@ -1384,6 +1397,16 @@ public: return SourceRange(getLParenLoc(), getRParenLoc()); } + SourceRange getExceptionSpecRange() const { + if (hasExceptionSpec()) + return *getExceptionSpecRangePtr(); + return SourceRange(); + } + void setExceptionSpecRange(SourceRange R) { + if (hasExceptionSpec()) + *getExceptionSpecRangePtr() = R; + } + ArrayRef<ParmVarDecl *> getParams() const { return llvm::makeArrayRef(getParmArray(), getNumParams()); } @@ -1416,12 +1439,15 @@ public: setLocalRangeEnd(Loc); for (unsigned i = 0, e = getNumParams(); i != e; ++i) setParam(i, nullptr); + if (hasExceptionSpec()) + setExceptionSpecRange(Loc); } /// \brief Returns the size of the type source info data block that is /// specific to this type. unsigned getExtraLocalDataSize() const { - return getNumParams() * sizeof(ParmVarDecl *); + unsigned ExceptSpecSize = hasExceptionSpec() ? sizeof(SourceRange) : 0; + return (getNumParams() * sizeof(ParmVarDecl *)) + ExceptSpecSize; } unsigned getExtraLocalDataAlignment() const { return alignof(ParmVarDecl *); } diff --git a/include/clang/Basic/AttrDocs.td b/include/clang/Basic/AttrDocs.td index 49b0a533cec3..8f6a7ea601b3 100644 --- a/include/clang/Basic/AttrDocs.td +++ b/include/clang/Basic/AttrDocs.td @@ -386,6 +386,7 @@ warnings or errors at compile-time if calls to the attributed function meet certain user-defined criteria. For example: .. code-block:: c + void abs(int a) __attribute__((diagnose_if(a >= 0, "Redundant abs call", "warning"))); void must_abs(int a) diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 6a8933f23ecd..3971cf60d5e0 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -8720,10 +8720,6 @@ def err_coroutine_invalid_func_context : Error< "|a copy assignment operator|a move assignment operator|the 'main' function" "|a constexpr function|a function with a deduced return type" "|a varargs function}0">; -def ext_coroutine_without_co_await_co_yield : ExtWarn< - "'co_return' used in a function " - "that uses neither 'co_await' nor 'co_yield'">, - InGroup<DiagGroup<"coreturn-without-coawait">>; def err_implied_std_coroutine_traits_not_found : Error< "you need to include <experimental/coroutine> before defining a coroutine">; def err_malformed_std_coroutine_traits : Error< diff --git a/include/clang/Basic/OpenMPKinds.def b/include/clang/Basic/OpenMPKinds.def index 58b54ce0bcd6..74ec26f19ac2 100644 --- a/include/clang/Basic/OpenMPKinds.def +++ b/include/clang/Basic/OpenMPKinds.def @@ -165,6 +165,9 @@ #ifndef OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE #define OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(Name) #endif +#ifndef OPENMP_TARGET_TEAMS_DISTRIBUTE_SIMD_CLAUSE +#define OPENMP_TARGET_TEAMS_DISTRIBUTE_SIMD_CLAUSE(Name) +#endif // OpenMP directives. OPENMP_DIRECTIVE(threadprivate) @@ -218,6 +221,7 @@ OPENMP_DIRECTIVE_EXT(target_teams, "target teams") OPENMP_DIRECTIVE_EXT(target_teams_distribute, "target teams distribute") OPENMP_DIRECTIVE_EXT(target_teams_distribute_parallel_for, "target teams distribute parallel for") OPENMP_DIRECTIVE_EXT(target_teams_distribute_parallel_for_simd, "target teams distribute parallel for simd") +OPENMP_DIRECTIVE_EXT(target_teams_distribute_simd, "target teams distribute simd") // OpenMP clauses. OPENMP_CLAUSE(if, OMPIfClause) @@ -446,7 +450,6 @@ OPENMP_TARGET_CLAUSE(firstprivate) OPENMP_TARGET_CLAUSE(is_device_ptr) // Clauses allowed for OpenMP directive 'target data'. -// TODO More clauses for 'target data' directive. OPENMP_TARGET_DATA_CLAUSE(if) OPENMP_TARGET_DATA_CLAUSE(device) OPENMP_TARGET_DATA_CLAUSE(map) @@ -483,7 +486,6 @@ OPENMP_TARGET_PARALLEL_CLAUSE(reduction) OPENMP_TARGET_PARALLEL_CLAUSE(is_device_ptr) // Clauses allowed for OpenMP directive 'target parallel for'. -// TODO: add target clauses 'is_device_ptr' OPENMP_TARGET_PARALLEL_FOR_CLAUSE(if) OPENMP_TARGET_PARALLEL_FOR_CLAUSE(device) OPENMP_TARGET_PARALLEL_FOR_CLAUSE(map) @@ -502,9 +504,9 @@ OPENMP_TARGET_PARALLEL_FOR_CLAUSE(collapse) OPENMP_TARGET_PARALLEL_FOR_CLAUSE(schedule) OPENMP_TARGET_PARALLEL_FOR_CLAUSE(ordered) OPENMP_TARGET_PARALLEL_FOR_CLAUSE(linear) +OPENMP_TARGET_PARALLEL_FOR_CLAUSE(is_device_ptr) // Clauses allowed for OpenMP directive 'target update'. -// TODO More clauses for 'target update' directive. OPENMP_TARGET_UPDATE_CLAUSE(if) OPENMP_TARGET_UPDATE_CLAUSE(device) OPENMP_TARGET_UPDATE_CLAUSE(to) @@ -513,7 +515,6 @@ OPENMP_TARGET_UPDATE_CLAUSE(nowait) OPENMP_TARGET_UPDATE_CLAUSE(depend) // Clauses allowed for OpenMP directive 'teams'. -// TODO More clauses for 'teams' directive. OPENMP_TEAMS_CLAUSE(default) OPENMP_TEAMS_CLAUSE(private) OPENMP_TEAMS_CLAUSE(firstprivate) @@ -523,7 +524,6 @@ OPENMP_TEAMS_CLAUSE(num_teams) OPENMP_TEAMS_CLAUSE(thread_limit) // Clauses allowed for OpenMP directive 'ordered'. -// TODO More clauses for 'ordered' directive. OPENMP_ORDERED_CLAUSE(threads) OPENMP_ORDERED_CLAUSE(simd) OPENMP_ORDERED_CLAUSE(depend) @@ -633,7 +633,6 @@ OPENMP_DISTRIBUTE_SIMD_CLAUSE(simdlen) OPENMP_DISTRIBUTE_SIMD_CLAUSE(reduction) // Clauses allowed for OpenMP directive 'target parallel for simd'. -// TODO: add target clauses 'is_device_ptr' OPENMP_TARGET_PARALLEL_FOR_SIMD_CLAUSE(if) OPENMP_TARGET_PARALLEL_FOR_SIMD_CLAUSE(device) OPENMP_TARGET_PARALLEL_FOR_SIMD_CLAUSE(map) @@ -655,6 +654,7 @@ OPENMP_TARGET_PARALLEL_FOR_SIMD_CLAUSE(linear) OPENMP_TARGET_PARALLEL_FOR_SIMD_CLAUSE(safelen) OPENMP_TARGET_PARALLEL_FOR_SIMD_CLAUSE(simdlen) OPENMP_TARGET_PARALLEL_FOR_SIMD_CLAUSE(aligned) +OPENMP_TARGET_PARALLEL_FOR_SIMD_CLAUSE(is_device_ptr) // Clauses allowed for OpenMP directive 'target simd'. OPENMP_TARGET_SIMD_CLAUSE(if) @@ -824,6 +824,28 @@ OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(aligned) OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(safelen) OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(simdlen) +// Clauses allowed for OpenMP directive 'target teams distribute simd'. +OPENMP_TARGET_TEAMS_DISTRIBUTE_SIMD_CLAUSE(if) +OPENMP_TARGET_TEAMS_DISTRIBUTE_SIMD_CLAUSE(device) +OPENMP_TARGET_TEAMS_DISTRIBUTE_SIMD_CLAUSE(map) +OPENMP_TARGET_TEAMS_DISTRIBUTE_SIMD_CLAUSE(private) +OPENMP_TARGET_TEAMS_DISTRIBUTE_SIMD_CLAUSE(nowait) +OPENMP_TARGET_TEAMS_DISTRIBUTE_SIMD_CLAUSE(depend) +OPENMP_TARGET_TEAMS_DISTRIBUTE_SIMD_CLAUSE(defaultmap) +OPENMP_TARGET_TEAMS_DISTRIBUTE_SIMD_CLAUSE(firstprivate) +OPENMP_TARGET_TEAMS_DISTRIBUTE_SIMD_CLAUSE(lastprivate) +OPENMP_TARGET_TEAMS_DISTRIBUTE_SIMD_CLAUSE(is_device_ptr) +OPENMP_TARGET_TEAMS_DISTRIBUTE_SIMD_CLAUSE(shared) +OPENMP_TARGET_TEAMS_DISTRIBUTE_SIMD_CLAUSE(reduction) +OPENMP_TARGET_TEAMS_DISTRIBUTE_SIMD_CLAUSE(num_teams) +OPENMP_TARGET_TEAMS_DISTRIBUTE_SIMD_CLAUSE(thread_limit) +OPENMP_TARGET_TEAMS_DISTRIBUTE_SIMD_CLAUSE(collapse) +OPENMP_TARGET_TEAMS_DISTRIBUTE_SIMD_CLAUSE(dist_schedule) +OPENMP_TARGET_TEAMS_DISTRIBUTE_SIMD_CLAUSE(linear) +OPENMP_TARGET_TEAMS_DISTRIBUTE_SIMD_CLAUSE(aligned) +OPENMP_TARGET_TEAMS_DISTRIBUTE_SIMD_CLAUSE(safelen) +OPENMP_TARGET_TEAMS_DISTRIBUTE_SIMD_CLAUSE(simdlen) + #undef OPENMP_TASKLOOP_SIMD_CLAUSE #undef OPENMP_TASKLOOP_CLAUSE #undef OPENMP_LINEAR_KIND @@ -875,3 +897,4 @@ OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(simdlen) #undef OPENMP_TARGET_TEAMS_DISTRIBUTE_CLAUSE #undef OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE #undef OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE +#undef OPENMP_TARGET_TEAMS_DISTRIBUTE_SIMD_CLAUSE diff --git a/include/clang/Basic/StmtNodes.td b/include/clang/Basic/StmtNodes.td index 2e92e5006ff4..67a5ab773aa6 100644 --- a/include/clang/Basic/StmtNodes.td +++ b/include/clang/Basic/StmtNodes.td @@ -244,3 +244,4 @@ def OMPTargetTeamsDirective : DStmt<OMPExecutableDirective>; def OMPTargetTeamsDistributeDirective : DStmt<OMPLoopDirective>; def OMPTargetTeamsDistributeParallelForDirective : DStmt<OMPLoopDirective>; def OMPTargetTeamsDistributeParallelForSimdDirective : DStmt<OMPLoopDirective>; +def OMPTargetTeamsDistributeSimdDirective : DStmt<OMPLoopDirective>; diff --git a/include/clang/Driver/CLCompatOptions.td b/include/clang/Driver/CLCompatOptions.td index cb2745afb7e4..60048c49c0f7 100644 --- a/include/clang/Driver/CLCompatOptions.td +++ b/include/clang/Driver/CLCompatOptions.td @@ -27,7 +27,7 @@ class CLCompileFlag<string name> : Option<["/", "-"], name, KIND_FLAG>, Group<cl_compile_Group>, Flags<[CLOption, DriverOption]>; class CLIgnoredFlag<string name> : Option<["/", "-"], name, KIND_FLAG>, - Group<cl_ignored_Group>, Flags<[CLOption, DriverOption, HelpHidden]>; + Group<cl_ignored_Group>, Flags<[CLOption, DriverOption]>; class CLJoined<string name> : Option<["/", "-"], name, KIND_JOINED>, Group<cl_Group>, Flags<[CLOption, DriverOption]>; @@ -299,7 +299,7 @@ def _SLASH_d2Zi_PLUS : CLIgnoredFlag<"d2Zi+">; def _SLASH_errorReport : CLIgnoredJoined<"errorReport">; def _SLASH_FC : CLIgnoredFlag<"FC">; def _SLASH_Fd : CLIgnoredJoined<"Fd">; -def _SLASH_FS : CLIgnoredFlag<"FS">, HelpText<"Force synchronous PDB writes">; +def _SLASH_FS : CLIgnoredFlag<"FS">; def _SLASH_GF : CLIgnoredFlag<"GF">; def _SLASH_kernel_ : CLIgnoredFlag<"kernel-">; def _SLASH_nologo : CLIgnoredFlag<"nologo">; @@ -308,7 +308,8 @@ def _SLASH_openmp_ : CLIgnoredFlag<"openmp-">; def _SLASH_RTC : CLIgnoredJoined<"RTC">; def _SLASH_sdl : CLIgnoredFlag<"sdl">; def _SLASH_sdl_ : CLIgnoredFlag<"sdl-">; -def _SLASH_utf8 : CLIgnoredFlag<"utf-8">; +def _SLASH_utf8 : CLIgnoredFlag<"utf-8">, + HelpText<"Set source and runtime encoding to UTF-8 (default)">; def _SLASH_w : CLIgnoredJoined<"w">; def _SLASH_Zc_auto : CLIgnoredFlag<"Zc:auto">; def _SLASH_Zc_forScope : CLIgnoredFlag<"Zc:forScope">; diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 7f4e59a2d233..6be159fad694 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -1032,6 +1032,7 @@ def fno_ms_extensions : Flag<["-"], "fno-ms-extensions">, Group<f_Group>, def fno_ms_compatibility : Flag<["-"], "fno-ms-compatibility">, Group<f_Group>, Flags<[CoreOption]>; def fno_delayed_template_parsing : Flag<["-"], "fno-delayed-template-parsing">, Group<f_Group>, + HelpText<"Disable delayed template parsing">, Flags<[DriverOption, CoreOption]>; def fno_objc_exceptions: Flag<["-"], "fno-objc-exceptions">, Group<f_Group>; def fno_objc_legacy_dispatch : Flag<["-"], "fno-objc-legacy-dispatch">, Group<f_Group>; diff --git a/include/clang/Index/IndexSymbol.h b/include/clang/Index/IndexSymbol.h index 559b212b9266..d19e5ebef2f0 100644 --- a/include/clang/Index/IndexSymbol.h +++ b/include/clang/Index/IndexSymbol.h @@ -64,6 +64,8 @@ enum class SymbolSubKind { None, CXXCopyConstructor, CXXMoveConstructor, + AccessorGetter, + AccessorSetter, }; /// Set of properties that provide additional info about a symbol. @@ -80,7 +82,7 @@ static const unsigned SymbolPropertyBitNum = 7; typedef unsigned SymbolPropertySet; /// Set of roles that are attributed to symbol occurrences. -enum class SymbolRole : uint16_t { +enum class SymbolRole : uint32_t { Declaration = 1 << 0, Definition = 1 << 1, Reference = 1 << 2, @@ -99,8 +101,10 @@ enum class SymbolRole : uint16_t { RelationCalledBy = 1 << 13, RelationExtendedBy = 1 << 14, RelationAccessorOf = 1 << 15, + RelationContainedBy = 1 << 16, + RelationIBTypeOf = 1 << 17, }; -static const unsigned SymbolRoleBitNum = 16; +static const unsigned SymbolRoleBitNum = 18; typedef unsigned SymbolRoleSet; /// Represents a relation to another symbol for a symbol occurrence. diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h index 4df3e783117a..51983b9ab5d8 100644 --- a/include/clang/Lex/HeaderSearch.h +++ b/include/clang/Lex/HeaderSearch.h @@ -406,7 +406,8 @@ public: /// \return false if \#including the file will have no effect or true /// if we should include it. bool ShouldEnterIncludeFile(Preprocessor &PP, const FileEntry *File, - bool isImport, Module *CorrespondingModule); + bool isImport, bool ModulesEnabled, + Module *CorrespondingModule); /// \brief Return whether the specified file is a normal header, /// a system header, or a C++ friendly system header. diff --git a/include/clang/Lex/ModuleMap.h b/include/clang/Lex/ModuleMap.h index b3a2421af86e..46136725d87a 100644 --- a/include/clang/Lex/ModuleMap.h +++ b/include/clang/Lex/ModuleMap.h @@ -316,6 +316,14 @@ public: BuiltinIncludeDir = Dir; } + /// \brief Get the directory that contains Clang-supplied include files. + const DirectoryEntry *getBuiltinDir() const { + return BuiltinIncludeDir; + } + + /// \brief Is this a compiler builtin header? + static bool isBuiltinHeader(StringRef FileName); + /// \brief Add a module map callback. void addModuleMapCallbacks(std::unique_ptr<ModuleMapCallbacks> Callback) { Callbacks.push_back(std::move(Callback)); diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 972f13daca46..fe159022c223 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -600,11 +600,8 @@ private: public: // If NeedType is true, then TryAnnotateTypeOrScopeToken will try harder to // find a type name by attempting typo correction. - bool TryAnnotateTypeOrScopeToken(bool EnteringContext = false, - bool NeedType = false); - bool TryAnnotateTypeOrScopeTokenAfterScopeSpec(bool EnteringContext, - bool NeedType, - CXXScopeSpec &SS, + bool TryAnnotateTypeOrScopeToken(); + bool TryAnnotateTypeOrScopeTokenAfterScopeSpec(CXXScopeSpec &SS, bool IsNewScope); bool TryAnnotateCXXScopeToken(bool EnteringContext = false); diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index d5e4b069f8b7..c180a8ea3ee1 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -1709,7 +1709,8 @@ public: static bool adjustContextForLocalExternDecl(DeclContext *&DC); void DiagnoseFunctionSpecifiers(const DeclSpec &DS); - void CheckShadow(Scope *S, VarDecl *D, const LookupResult& R); + NamedDecl *getShadowedDeclaration(const VarDecl *D, const LookupResult &R); + void CheckShadow(VarDecl *D, NamedDecl *ShadowedDecl, const LookupResult &R); void CheckShadow(Scope *S, VarDecl *D); /// Warn if 'E', which is an expression that is about to be modified, refers @@ -1790,9 +1791,8 @@ public: bool SetParamDefaultArgument(ParmVarDecl *Param, Expr *DefaultArg, SourceLocation EqualLoc); - void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit, - bool TypeMayContainAuto); - void ActOnUninitializedDecl(Decl *dcl, bool TypeMayContainAuto); + void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit); + void ActOnUninitializedDecl(Decl *dcl); void ActOnInitializerError(Decl *Dcl); bool canInitializeWithParenthesizedList(QualType TargetType); @@ -1807,8 +1807,7 @@ public: void FinalizeDeclaration(Decl *D); DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS, ArrayRef<Decl *> Group); - DeclGroupPtrTy BuildDeclaratorGroup(MutableArrayRef<Decl *> Group, - bool TypeMayContainAuto = true); + DeclGroupPtrTy BuildDeclaratorGroup(MutableArrayRef<Decl *> Group); /// Should be called on all declarations that might have attached /// documentation comments. @@ -4920,8 +4919,7 @@ public: TypeSourceInfo *AllocTypeInfo, Expr *ArraySize, SourceRange DirectInitRange, - Expr *Initializer, - bool TypeMayContainAuto = true); + Expr *Initializer); bool CheckAllocatedType(QualType AllocType, SourceLocation Loc, SourceRange R); @@ -8584,6 +8582,12 @@ public: ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA); + /// Called on well-formed '\#pragma omp target teams distribute simd' after + /// parsing of the associated statement. + StmtResult ActOnOpenMPTargetTeamsDistributeSimdDirective( + ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc, + llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA); /// Checks correctness of linear modifiers. bool CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind, diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h index 61e2f18045ea..acbd6d1deb5b 100644 --- a/include/clang/Serialization/ASTBitCodes.h +++ b/include/clang/Serialization/ASTBitCodes.h @@ -1517,6 +1517,7 @@ namespace clang { STMT_OMP_TARGET_TEAMS_DISTRIBUTE_DIRECTIVE, STMT_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_DIRECTIVE, STMT_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_DIRECTIVE, + STMT_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD_DIRECTIVE, EXPR_OMP_ARRAY_SECTION, // ARC diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 67e96ea828bd..1ccb746633a7 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -4671,8 +4671,7 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { ClassTemplateDecl *D2 = ClassTemplateDecl::Create(Importer.getToContext(), DC, Loc, Name, TemplateParams, - D2Templated, - /*PrevDecl=*/nullptr); + D2Templated); D2Templated->setDescribedClassTemplate(D2); D2->setAccess(D->getAccess()); diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index c3fa1c87affd..81f08787d515 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -2990,6 +2990,18 @@ SourceRange FunctionDecl::getReturnTypeSourceRange() const { return RTRange; } +SourceRange FunctionDecl::getExceptionSpecSourceRange() const { + const TypeSourceInfo *TSI = getTypeSourceInfo(); + if (!TSI) + return SourceRange(); + FunctionTypeLoc FTL = + TSI->getTypeLoc().IgnoreParens().getAs<FunctionTypeLoc>(); + if (!FTL) + return SourceRange(); + + return FTL.getExceptionSpecRange(); +} + const Attr *FunctionDecl::getUnusedResultAttr() const { QualType RetType = getReturnType(); if (RetType->isRecordType()) { diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp index 8643cbfcd960..a5fbb0a3baec 100644 --- a/lib/AST/DeclTemplate.cpp +++ b/lib/AST/DeclTemplate.cpp @@ -297,12 +297,10 @@ ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, - NamedDecl *Decl, - ClassTemplateDecl *PrevDecl) { + NamedDecl *Decl) { AdoptTemplateParameterList(Params, cast<DeclContext>(Decl)); ClassTemplateDecl *New = new (C, DC) ClassTemplateDecl(C, DC, L, Name, Params, Decl); - New->setPreviousDecl(PrevDecl); return New; } diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 93f3ad5f2bdd..14f31d0c6b8c 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -562,8 +562,7 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { FT = dyn_cast<FunctionProtoType>(AFT); if (IT == FuncSig) { - assert(FT && "We must have a written prototype in this case."); - switch (FT->getCallConv()) { + switch (AFT->getCallConv()) { case CC_C: POut << "__cdecl "; break; case CC_X86StdCall: POut << "__stdcall "; break; case CC_X86FastCall: POut << "__fastcall "; break; @@ -587,12 +586,15 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { if (FT->isVariadic()) { if (FD->getNumParams()) POut << ", "; POut << "..."; + } else if ((IT == FuncSig || !Context.getLangOpts().CPlusPlus) && + !Decl->getNumParams()) { + POut << "void"; } } POut << ")"; if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) { - const FunctionType *FT = MD->getType()->castAs<FunctionType>(); + assert(FT && "We must have a written prototype in this case."); if (FT->isConst()) POut << " const"; if (FT->isVolatile()) diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index fe77c7f6f3bf..a8512b294055 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -1627,8 +1627,17 @@ static bool CheckLiteralType(EvalInfo &Info, const Expr *E, // C++1y: A constant initializer for an object o [...] may also invoke // constexpr constructors for o and its subobjects even if those objects // are of non-literal class types. - if (Info.getLangOpts().CPlusPlus14 && This && - Info.EvaluatingDecl == This->getLValueBase()) + // + // C++11 missed this detail for aggregates, so classes like this: + // struct foo_t { union { int i; volatile int j; } u; }; + // are not (obviously) initializable like so: + // __attribute__((__require_constant_initialization__)) + // static const foo_t x = {{0}}; + // because "i" is a subobject with non-literal initialization (due to the + // volatile member of the union). See: + // http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1677 + // Therefore, we use the C++1y behavior. + if (This && Info.EvaluatingDecl == This->getLValueBase()) return true; // Prvalue constant expressions must be of literal types. diff --git a/lib/AST/StmtOpenMP.cpp b/lib/AST/StmtOpenMP.cpp index a7c71bb5f45c..880817a1339b 100644 --- a/lib/AST/StmtOpenMP.cpp +++ b/lib/AST/StmtOpenMP.cpp @@ -1720,3 +1720,59 @@ OMPTargetTeamsDistributeParallelForSimdDirective::CreateEmpty( CollapsedNum, NumClauses); } +OMPTargetTeamsDistributeSimdDirective * +OMPTargetTeamsDistributeSimdDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, + const HelperExprs &Exprs) { + auto Size = llvm::alignTo(sizeof(OMPTargetTeamsDistributeSimdDirective), + alignof(OMPClause *)); + void *Mem = C.Allocate( + Size + sizeof(OMPClause *) * Clauses.size() + + sizeof(Stmt *) * + numLoopChildren(CollapsedNum, OMPD_target_teams_distribute_simd)); + OMPTargetTeamsDistributeSimdDirective *Dir = new (Mem) + OMPTargetTeamsDistributeSimdDirective(StartLoc, EndLoc, CollapsedNum, + Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + Dir->setIterationVariable(Exprs.IterationVarRef); + Dir->setLastIteration(Exprs.LastIteration); + Dir->setCalcLastIteration(Exprs.CalcLastIteration); + Dir->setPreCond(Exprs.PreCond); + Dir->setCond(Exprs.Cond); + Dir->setInit(Exprs.Init); + Dir->setInc(Exprs.Inc); + Dir->setIsLastIterVariable(Exprs.IL); + Dir->setLowerBoundVariable(Exprs.LB); + Dir->setUpperBoundVariable(Exprs.UB); + Dir->setStrideVariable(Exprs.ST); + Dir->setEnsureUpperBound(Exprs.EUB); + Dir->setNextLowerBound(Exprs.NLB); + Dir->setNextUpperBound(Exprs.NUB); + Dir->setNumIterations(Exprs.NumIterations); + Dir->setPrevLowerBoundVariable(Exprs.PrevLB); + Dir->setPrevUpperBoundVariable(Exprs.PrevUB); + Dir->setCounters(Exprs.Counters); + Dir->setPrivateCounters(Exprs.PrivateCounters); + Dir->setInits(Exprs.Inits); + Dir->setUpdates(Exprs.Updates); + Dir->setFinals(Exprs.Finals); + Dir->setPreInits(Exprs.PreInits); + return Dir; +} + +OMPTargetTeamsDistributeSimdDirective * +OMPTargetTeamsDistributeSimdDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, + EmptyShell) { + auto Size = llvm::alignTo(sizeof(OMPTargetTeamsDistributeSimdDirective), + alignof(OMPClause *)); + void *Mem = C.Allocate( + Size + sizeof(OMPClause *) * NumClauses + + sizeof(Stmt *) * + numLoopChildren(CollapsedNum, OMPD_target_teams_distribute_simd)); + return new (Mem) + OMPTargetTeamsDistributeSimdDirective(CollapsedNum, NumClauses); +} diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index a9c64c3ba6ae..1ba1aa40ec5c 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -1250,6 +1250,12 @@ void StmtPrinter::VisitOMPTargetTeamsDistributeParallelForSimdDirective( PrintOMPExecutableDirective(Node); } +void StmtPrinter::VisitOMPTargetTeamsDistributeSimdDirective( + OMPTargetTeamsDistributeSimdDirective *Node) { + Indent() << "#pragma omp target teams distribute simd "; + PrintOMPExecutableDirective(Node); +} + //===----------------------------------------------------------------------===// // Expr printing methods. //===----------------------------------------------------------------------===// diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp index df36bf06b843..bcd2e96875e7 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -768,6 +768,11 @@ void StmtProfiler::VisitOMPTargetTeamsDistributeParallelForSimdDirective( VisitOMPLoopDirective(S); } +void StmtProfiler::VisitOMPTargetTeamsDistributeSimdDirective( + const OMPTargetTeamsDistributeSimdDirective *S) { + VisitOMPLoopDirective(S); +} + void StmtProfiler::VisitExpr(const Expr *S) { VisitStmt(S); } diff --git a/lib/Analysis/BodyFarm.cpp b/lib/Analysis/BodyFarm.cpp index d202a0406461..56c812c34c50 100644 --- a/lib/Analysis/BodyFarm.cpp +++ b/lib/Analysis/BodyFarm.cpp @@ -467,6 +467,8 @@ static Stmt *createObjCPropertyGetter(ASTContext &Ctx, ASTMaker M(Ctx); const VarDecl *selfVar = Prop->getGetterMethodDecl()->getSelfDecl(); + if (!selfVar) + return nullptr; Expr *loadedIVar = M.makeObjCIvarRef( diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp index a1a463f1d037..d56e0e8fa1d0 100644 --- a/lib/Analysis/CFG.cpp +++ b/lib/Analysis/CFG.cpp @@ -2175,19 +2175,15 @@ CFGBlock *CFGBuilder::VisitIfStmt(IfStmt *I) { SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); // Create local scope for C++17 if init-stmt if one exists. - if (Stmt *Init = I->getInit()) { - LocalScope::const_iterator BeginScopePos = ScopePos; + if (Stmt *Init = I->getInit()) addLocalScopeForStmt(Init); - addAutomaticObjDtors(ScopePos, BeginScopePos, I); - } // Create local scope for possible condition variable. // Store scope position. Add implicit destructor. - if (VarDecl *VD = I->getConditionVariable()) { - LocalScope::const_iterator BeginScopePos = ScopePos; + if (VarDecl *VD = I->getConditionVariable()) addLocalScopeForVarDecl(VD); - addAutomaticObjDtors(ScopePos, BeginScopePos, I); - } + + addAutomaticObjDtors(ScopePos, save_scope_pos.get(), I); // The block we were processing is now finished. Make it the successor // block. @@ -2256,36 +2252,39 @@ CFGBlock *CFGBuilder::VisitIfStmt(IfStmt *I) { // removes infeasible paths from the control-flow graph by having the // control-flow transfer of '&&' or '||' go directly into the then/else // blocks directly. - if (!I->getConditionVariable()) - if (BinaryOperator *Cond = - dyn_cast<BinaryOperator>(I->getCond()->IgnoreParens())) - if (Cond->isLogicalOp()) - return VisitLogicalOperator(Cond, I, ThenBlock, ElseBlock).first; - - // Now create a new block containing the if statement. - Block = createBlock(false); + BinaryOperator *Cond = + I->getConditionVariable() + ? nullptr + : dyn_cast<BinaryOperator>(I->getCond()->IgnoreParens()); + CFGBlock *LastBlock; + if (Cond && Cond->isLogicalOp()) + LastBlock = VisitLogicalOperator(Cond, I, ThenBlock, ElseBlock).first; + else { + // Now create a new block containing the if statement. + Block = createBlock(false); - // Set the terminator of the new block to the If statement. - Block->setTerminator(I); + // Set the terminator of the new block to the If statement. + Block->setTerminator(I); - // See if this is a known constant. - const TryResult &KnownVal = tryEvaluateBool(I->getCond()); + // See if this is a known constant. + const TryResult &KnownVal = tryEvaluateBool(I->getCond()); - // Add the successors. If we know that specific branches are - // unreachable, inform addSuccessor() of that knowledge. - addSuccessor(Block, ThenBlock, /* isReachable = */ !KnownVal.isFalse()); - addSuccessor(Block, ElseBlock, /* isReachable = */ !KnownVal.isTrue()); + // Add the successors. If we know that specific branches are + // unreachable, inform addSuccessor() of that knowledge. + addSuccessor(Block, ThenBlock, /* isReachable = */ !KnownVal.isFalse()); + addSuccessor(Block, ElseBlock, /* isReachable = */ !KnownVal.isTrue()); - // Add the condition as the last statement in the new block. This may create - // new blocks as the condition may contain control-flow. Any newly created - // blocks will be pointed to be "Block". - CFGBlock *LastBlock = addStmt(I->getCond()); + // Add the condition as the last statement in the new block. This may + // create new blocks as the condition may contain control-flow. Any newly + // created blocks will be pointed to be "Block". + LastBlock = addStmt(I->getCond()); - // If the IfStmt contains a condition variable, add it and its - // initializer to the CFG. - if (const DeclStmt* DS = I->getConditionVariableDeclStmt()) { - autoCreateBlock(); - LastBlock = addStmt(const_cast<DeclStmt *>(DS)); + // If the IfStmt contains a condition variable, add it and its + // initializer to the CFG. + if (const DeclStmt* DS = I->getConditionVariableDeclStmt()) { + autoCreateBlock(); + LastBlock = addStmt(const_cast<DeclStmt *>(DS)); + } } // Finally, if the IfStmt contains a C++17 init-stmt, add it to the CFG. @@ -3078,19 +3077,15 @@ CFGBlock *CFGBuilder::VisitSwitchStmt(SwitchStmt *Terminator) { SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); // Create local scope for C++17 switch init-stmt if one exists. - if (Stmt *Init = Terminator->getInit()) { - LocalScope::const_iterator BeginScopePos = ScopePos; + if (Stmt *Init = Terminator->getInit()) addLocalScopeForStmt(Init); - addAutomaticObjDtors(ScopePos, BeginScopePos, Terminator); - } // Create local scope for possible condition variable. // Store scope position. Add implicit destructor. - if (VarDecl *VD = Terminator->getConditionVariable()) { - LocalScope::const_iterator SwitchBeginScopePos = ScopePos; + if (VarDecl *VD = Terminator->getConditionVariable()) addLocalScopeForVarDecl(VD); - addAutomaticObjDtors(ScopePos, SwitchBeginScopePos, Terminator); - } + + addAutomaticObjDtors(ScopePos, save_scope_pos.get(), Terminator); if (Block) { if (badCFG) diff --git a/lib/Analysis/ReachableCode.cpp b/lib/Analysis/ReachableCode.cpp index 69d000c03bac..a2f3203762f7 100644 --- a/lib/Analysis/ReachableCode.cpp +++ b/lib/Analysis/ReachableCode.cpp @@ -218,11 +218,21 @@ static bool isConfigurationValue(const Stmt *S, } case Stmt::UnaryOperatorClass: { const UnaryOperator *UO = cast<UnaryOperator>(S); - if (SilenceableCondVal) - *SilenceableCondVal = UO->getSourceRange(); - return UO->getOpcode() == UO_LNot && - isConfigurationValue(UO->getSubExpr(), PP, SilenceableCondVal, - IncludeIntegers, WrappedInParens); + if (UO->getOpcode() != UO_LNot) + return false; + bool SilenceableCondValNotSet = + SilenceableCondVal && SilenceableCondVal->getBegin().isInvalid(); + bool IsSubExprConfigValue = + isConfigurationValue(UO->getSubExpr(), PP, SilenceableCondVal, + IncludeIntegers, WrappedInParens); + // Update the silenceable condition value source range only if the range + // was set directly by the child expression. + if (SilenceableCondValNotSet && + SilenceableCondVal->getBegin().isValid() && + *SilenceableCondVal == + UO->getSubExpr()->IgnoreCasts()->getSourceRange()) + *SilenceableCondVal = UO->getSourceRange(); + return IsSubExprConfigValue; } default: return false; diff --git a/lib/Basic/OpenMPKinds.cpp b/lib/Basic/OpenMPKinds.cpp index 7bd1f8762bff..905c3693d378 100644 --- a/lib/Basic/OpenMPKinds.cpp +++ b/lib/Basic/OpenMPKinds.cpp @@ -700,6 +700,16 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind, break; } break; + case OMPD_target_teams_distribute_simd: + switch (CKind) { +#define OPENMP_TARGET_TEAMS_DISTRIBUTE_SIMD_CLAUSE(Name) \ + case OMPC_##Name: \ + return true; +#include "clang/Basic/OpenMPKinds.def" + default: + break; + } + break; case OMPD_declare_target: case OMPD_end_declare_target: case OMPD_unknown: @@ -732,7 +742,8 @@ bool clang::isOpenMPLoopDirective(OpenMPDirectiveKind DKind) { DKind == OMPD_teams_distribute_parallel_for || DKind == OMPD_target_teams_distribute || DKind == OMPD_target_teams_distribute_parallel_for || - DKind == OMPD_target_teams_distribute_parallel_for_simd; + DKind == OMPD_target_teams_distribute_parallel_for_simd || + DKind == OMPD_target_teams_distribute_simd; } bool clang::isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind) { @@ -773,7 +784,8 @@ bool clang::isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind) { DKind == OMPD_target_parallel_for_simd || DKind == OMPD_target_simd || DKind == OMPD_target_teams || DKind == OMPD_target_teams_distribute || DKind == OMPD_target_teams_distribute_parallel_for || - DKind == OMPD_target_teams_distribute_parallel_for_simd; + DKind == OMPD_target_teams_distribute_parallel_for_simd || + DKind == OMPD_target_teams_distribute_simd; } bool clang::isOpenMPTargetDataManagementDirective(OpenMPDirectiveKind DKind) { @@ -792,7 +804,8 @@ bool clang::isOpenMPTeamsDirective(OpenMPDirectiveKind DKind) { return isOpenMPNestingTeamsDirective(DKind) || DKind == OMPD_target_teams || DKind == OMPD_target_teams_distribute || DKind == OMPD_target_teams_distribute_parallel_for || - DKind == OMPD_target_teams_distribute_parallel_for_simd; + DKind == OMPD_target_teams_distribute_parallel_for_simd || + DKind == OMPD_target_teams_distribute_simd; } bool clang::isOpenMPSimdDirective(OpenMPDirectiveKind DKind) { @@ -802,7 +815,8 @@ bool clang::isOpenMPSimdDirective(OpenMPDirectiveKind DKind) { DKind == OMPD_distribute_simd || DKind == OMPD_target_simd || DKind == OMPD_teams_distribute_simd || DKind == OMPD_teams_distribute_parallel_for_simd || - DKind == OMPD_target_teams_distribute_parallel_for_simd; + DKind == OMPD_target_teams_distribute_parallel_for_simd || + DKind == OMPD_target_teams_distribute_simd; } bool clang::isOpenMPNestingDistributeDirective(OpenMPDirectiveKind Kind) { @@ -819,7 +833,8 @@ bool clang::isOpenMPDistributeDirective(OpenMPDirectiveKind Kind) { Kind == OMPD_teams_distribute_parallel_for || Kind == OMPD_target_teams_distribute || Kind == OMPD_target_teams_distribute_parallel_for || - Kind == OMPD_target_teams_distribute_parallel_for_simd; + Kind == OMPD_target_teams_distribute_parallel_for_simd || + Kind == OMPD_target_teams_distribute_simd; } bool clang::isOpenMPPrivate(OpenMPClauseKind Kind) { @@ -845,5 +860,6 @@ bool clang::isOpenMPLoopBoundSharingDirective(OpenMPDirectiveKind Kind) { Kind == OMPD_teams_distribute_parallel_for || Kind == OMPD_target_teams_distribute || Kind == OMPD_target_teams_distribute_parallel_for || - Kind == OMPD_target_teams_distribute_parallel_for_simd; + Kind == OMPD_target_teams_distribute_parallel_for_simd || + Kind == OMPD_target_teams_distribute_simd; } diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp index 4d2b3d007599..89e3f3ebbe3f 100644 --- a/lib/Basic/Targets.cpp +++ b/lib/Basic/Targets.cpp @@ -2663,6 +2663,12 @@ class X86TargetInfo : public TargetInfo { CK_BDVER4, //@} + /// \name zen + /// Zen architecture processors. + //@{ + CK_ZNVER1, + //@} + /// This specification is deprecated and will be removed in the future. /// Users should prefer \see CK_K8. // FIXME: Warn on this when the CPU is set to it. @@ -2744,6 +2750,7 @@ class X86TargetInfo : public TargetInfo { .Case("bdver2", CK_BDVER2) .Case("bdver3", CK_BDVER3) .Case("bdver4", CK_BDVER4) + .Case("znver1", CK_ZNVER1) .Case("x86-64", CK_x86_64) .Case("geode", CK_Geode) .Default(CK_Generic); @@ -2943,6 +2950,7 @@ public: case CK_BDVER2: case CK_BDVER3: case CK_BDVER4: + case CK_ZNVER1: case CK_x86_64: return true; } @@ -3190,6 +3198,33 @@ bool X86TargetInfo::initFeatureMap( setFeatureEnabledImpl(Features, "cx16", true); setFeatureEnabledImpl(Features, "fxsr", true); break; + case CK_ZNVER1: + setFeatureEnabledImpl(Features, "adx", true); + setFeatureEnabledImpl(Features, "aes", true); + setFeatureEnabledImpl(Features, "avx2", true); + setFeatureEnabledImpl(Features, "bmi", true); + setFeatureEnabledImpl(Features, "bmi2", true); + setFeatureEnabledImpl(Features, "clflushopt", true); + setFeatureEnabledImpl(Features, "cx16", true); + setFeatureEnabledImpl(Features, "f16c", true); + setFeatureEnabledImpl(Features, "fma", true); + setFeatureEnabledImpl(Features, "fsgsbase", true); + setFeatureEnabledImpl(Features, "fxsr", true); + setFeatureEnabledImpl(Features, "lzcnt", true); + setFeatureEnabledImpl(Features, "mwaitx", true); + setFeatureEnabledImpl(Features, "movbe", true); + setFeatureEnabledImpl(Features, "pclmul", true); + setFeatureEnabledImpl(Features, "popcnt", true); + setFeatureEnabledImpl(Features, "prfchw", true); + setFeatureEnabledImpl(Features, "rdrnd", true); + setFeatureEnabledImpl(Features, "rdseed", true); + setFeatureEnabledImpl(Features, "sha", true); + setFeatureEnabledImpl(Features, "sse4a", true); + setFeatureEnabledImpl(Features, "xsave", true); + setFeatureEnabledImpl(Features, "xsavec", true); + setFeatureEnabledImpl(Features, "xsaveopt", true); + setFeatureEnabledImpl(Features, "xsaves", true); + break; case CK_BDVER4: setFeatureEnabledImpl(Features, "avx2", true); setFeatureEnabledImpl(Features, "bmi2", true); @@ -3741,6 +3776,9 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts, case CK_BDVER4: defineCPUMacros(Builder, "bdver4"); break; + case CK_ZNVER1: + defineCPUMacros(Builder, "znver1"); + break; case CK_Geode: defineCPUMacros(Builder, "geode"); break; diff --git a/lib/Basic/Version.cpp b/lib/Basic/Version.cpp index a1a67c2bc144..b91efeb34c7f 100644 --- a/lib/Basic/Version.cpp +++ b/lib/Basic/Version.cpp @@ -36,7 +36,7 @@ std::string getClangRepositoryPath() { // If the SVN_REPOSITORY is empty, try to use the SVN keyword. This helps us // pick up a tag in an SVN export, for example. - StringRef SVNRepository("$URL: https://llvm.org/svn/llvm-project/cfe/trunk/lib/Basic/Version.cpp $"); + StringRef SVNRepository("$URL: https://llvm.org/svn/llvm-project/cfe/branches/release_40/lib/Basic/Version.cpp $"); if (URL.empty()) { URL = SVNRepository.slice(SVNRepository.find(':'), SVNRepository.find("/lib/Basic")); diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 4d34b3e9222f..2ede1d46b3d5 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -4318,9 +4318,9 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, } if (BuiltinID == ARM::BI__builtin_arm_rbit) { - return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::arm_rbit), - EmitScalarExpr(E->getArg(0)), - "rbit"); + llvm::Value *Arg = EmitScalarExpr(E->getArg(0)); + return Builder.CreateCall( + CGM.getIntrinsic(Intrinsic::bitreverse, Arg->getType()), Arg, "rbit"); } if (BuiltinID == ARM::BI__clear_cache) { @@ -5226,14 +5226,14 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID, "rbit of unusual size!"); llvm::Value *Arg = EmitScalarExpr(E->getArg(0)); return Builder.CreateCall( - CGM.getIntrinsic(Intrinsic::aarch64_rbit, Arg->getType()), Arg, "rbit"); + CGM.getIntrinsic(Intrinsic::bitreverse, Arg->getType()), Arg, "rbit"); } if (BuiltinID == AArch64::BI__builtin_arm_rbit64) { assert((getContext().getTypeSize(E->getType()) == 64) && "rbit of unusual size!"); llvm::Value *Arg = EmitScalarExpr(E->getArg(0)); return Builder.CreateCall( - CGM.getIntrinsic(Intrinsic::aarch64_rbit, Arg->getType()), Arg, "rbit"); + CGM.getIntrinsic(Intrinsic::bitreverse, Arg->getType()), Arg, "rbit"); } if (BuiltinID == AArch64::BI__clear_cache) { diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index d76136380160..0a88b2310beb 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -311,7 +311,7 @@ CodeGenFunction::AddInitializerToStaticVarDecl(const VarDecl &D, if (!Init) { if (!getLangOpts().CPlusPlus) CGM.ErrorUnsupported(D.getInit(), "constant l-value expression"); - else if (Builder.GetInsertBlock()) { + else if (HaveInsertPoint()) { // Since we have a static initializer, this global variable can't // be constant. GV->setConstant(false); @@ -352,7 +352,7 @@ CodeGenFunction::AddInitializerToStaticVarDecl(const VarDecl &D, GV->setConstant(CGM.isTypeConstant(D.getType(), true)); GV->setInitializer(Init); - if (hasNontrivialDestruction(D.getType())) { + if (hasNontrivialDestruction(D.getType()) && HaveInsertPoint()) { // We have a constant initializer, but a nontrivial destructor. We still // need to perform a guarded "initialization" in order to register the // destructor. diff --git a/lib/CodeGen/CGDeclCXX.cpp b/lib/CodeGen/CGDeclCXX.cpp index 8d9d0b21bfe1..f56e18216931 100644 --- a/lib/CodeGen/CGDeclCXX.cpp +++ b/lib/CodeGen/CGDeclCXX.cpp @@ -353,9 +353,6 @@ CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D, if (D->getTLSKind()) { // FIXME: Should we support init_priority for thread_local? - // FIXME: Ideally, initialization of instantiated thread_local static data - // members of class templates should not trigger initialization of other - // entities in the TU. // FIXME: We only need to register one __cxa_thread_atexit function for the // entire TU. CXXThreadLocalInits.push_back(Fn); diff --git a/lib/CodeGen/CGOpenMPRuntime.cpp b/lib/CodeGen/CGOpenMPRuntime.cpp index 27af344fae87..db9de2ab6ad5 100644 --- a/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/lib/CodeGen/CGOpenMPRuntime.cpp @@ -99,10 +99,11 @@ class CGOpenMPOutlinedRegionInfo final : public CGOpenMPRegionInfo { public: CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar, const RegionCodeGenTy &CodeGen, - OpenMPDirectiveKind Kind, bool HasCancel) + OpenMPDirectiveKind Kind, bool HasCancel, + StringRef HelperName) : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind, HasCancel), - ThreadIDVar(ThreadIDVar) { + ThreadIDVar(ThreadIDVar), HelperName(HelperName) { assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); } @@ -111,7 +112,7 @@ public: const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; } /// \brief Get the name of the capture helper. - StringRef getHelperName() const override { return ".omp_outlined."; } + StringRef getHelperName() const override { return HelperName; } static bool classof(const CGCapturedStmtInfo *Info) { return CGOpenMPRegionInfo::classof(Info) && @@ -123,6 +124,7 @@ private: /// \brief A variable or parameter storing global thread id for OpenMP /// constructs. const VarDecl *ThreadIDVar; + StringRef HelperName; }; /// \brief API for captured statement code generation in OpenMP constructs. @@ -855,7 +857,7 @@ llvm::Value *CGOpenMPRuntime::emitParallelOrTeamsOutlinedFunction( else if (auto *OPFD = dyn_cast<OMPParallelForDirective>(&D)) HasCancel = OPFD->hasCancel(); CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind, - HasCancel); + HasCancel, getOutlinedHelperName()); CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); return CGF.GenerateOpenMPCapturedStmtFunction(*CS); } @@ -1892,9 +1894,9 @@ llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition( /// } else { /// ElseGen(); /// } -static void emitOMPIfClause(CodeGenFunction &CGF, const Expr *Cond, - const RegionCodeGenTy &ThenGen, - const RegionCodeGenTy &ElseGen) { +void CGOpenMPRuntime::emitOMPIfClause(CodeGenFunction &CGF, const Expr *Cond, + const RegionCodeGenTy &ThenGen, + const RegionCodeGenTy &ElseGen) { CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange()); // If the condition constant folds and can be elided, try to avoid emitting diff --git a/lib/CodeGen/CGOpenMPRuntime.h b/lib/CodeGen/CGOpenMPRuntime.h index 9a784dff0ae8..61ddc702ed24 100644 --- a/lib/CodeGen/CGOpenMPRuntime.h +++ b/lib/CodeGen/CGOpenMPRuntime.h @@ -130,6 +130,35 @@ protected: bool IsOffloadEntry, const RegionCodeGenTy &CodeGen); + /// \brief Emits code for OpenMP 'if' clause using specified \a CodeGen + /// function. Here is the logic: + /// if (Cond) { + /// ThenGen(); + /// } else { + /// ElseGen(); + /// } + void emitOMPIfClause(CodeGenFunction &CGF, const Expr *Cond, + const RegionCodeGenTy &ThenGen, + const RegionCodeGenTy &ElseGen); + + /// \brief Emits object of ident_t type with info for source location. + /// \param Flags Flags for OpenMP location. + /// + llvm::Value *emitUpdateLocation(CodeGenFunction &CGF, SourceLocation Loc, + unsigned Flags = 0); + + /// \brief Returns pointer to ident_t type. + llvm::Type *getIdentTyPointerTy(); + + /// \brief Gets thread id value for the current thread. + /// + llvm::Value *getThreadID(CodeGenFunction &CGF, SourceLocation Loc); + + /// \brief Get the function name of an outlined region. + // The name can be customized depending on the target. + // + virtual StringRef getOutlinedHelperName() const { return ".omp_outlined."; } + private: /// \brief Default const ident_t object used for initialization of all other /// ident_t objects. @@ -388,15 +417,6 @@ private: /// \brief Build type kmp_routine_entry_t (if not built yet). void emitKmpRoutineEntryT(QualType KmpInt32Ty); - /// \brief Emits object of ident_t type with info for source location. - /// \param Flags Flags for OpenMP location. - /// - llvm::Value *emitUpdateLocation(CodeGenFunction &CGF, SourceLocation Loc, - unsigned Flags = 0); - - /// \brief Returns pointer to ident_t type. - llvm::Type *getIdentTyPointerTy(); - /// \brief Returns pointer to kmpc_micro type. llvm::Type *getKmpc_MicroPointerTy(); @@ -432,10 +452,6 @@ private: /// stored. virtual Address emitThreadIDAddress(CodeGenFunction &CGF, SourceLocation Loc); - /// \brief Gets thread id value for the current thread. - /// - llvm::Value *getThreadID(CodeGenFunction &CGF, SourceLocation Loc); - /// \brief Gets (if variable with the given name already exist) or creates /// internal global variable with the specified Name. The created variable has /// linkage CommonLinkage by default and is initialized by null value. diff --git a/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp b/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp index bc1458b1c203..6a6d832e33cd 100644 --- a/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp +++ b/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp @@ -26,8 +26,57 @@ enum OpenMPRTLFunctionNVPTX { OMPRTL_NVPTX__kmpc_kernel_init, /// \brief Call to void __kmpc_kernel_deinit(); OMPRTL_NVPTX__kmpc_kernel_deinit, + /// \brief Call to void __kmpc_kernel_prepare_parallel(void + /// *outlined_function); + OMPRTL_NVPTX__kmpc_kernel_prepare_parallel, + /// \brief Call to bool __kmpc_kernel_parallel(void **outlined_function); + OMPRTL_NVPTX__kmpc_kernel_parallel, + /// \brief Call to void __kmpc_kernel_end_parallel(); + OMPRTL_NVPTX__kmpc_kernel_end_parallel, + /// Call to void __kmpc_serialized_parallel(ident_t *loc, kmp_int32 + /// global_tid); + OMPRTL_NVPTX__kmpc_serialized_parallel, + /// Call to void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32 + /// global_tid); + OMPRTL_NVPTX__kmpc_end_serialized_parallel, }; -} // namespace + +/// Pre(post)-action for different OpenMP constructs specialized for NVPTX. +class NVPTXActionTy final : public PrePostActionTy { + llvm::Value *EnterCallee; + ArrayRef<llvm::Value *> EnterArgs; + llvm::Value *ExitCallee; + ArrayRef<llvm::Value *> ExitArgs; + bool Conditional; + llvm::BasicBlock *ContBlock = nullptr; + +public: + NVPTXActionTy(llvm::Value *EnterCallee, ArrayRef<llvm::Value *> EnterArgs, + llvm::Value *ExitCallee, ArrayRef<llvm::Value *> ExitArgs, + bool Conditional = false) + : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee), + ExitArgs(ExitArgs), Conditional(Conditional) {} + void Enter(CodeGenFunction &CGF) override { + llvm::Value *EnterRes = CGF.EmitRuntimeCall(EnterCallee, EnterArgs); + if (Conditional) { + llvm::Value *CallBool = CGF.Builder.CreateIsNotNull(EnterRes); + auto *ThenBlock = CGF.createBasicBlock("omp_if.then"); + ContBlock = CGF.createBasicBlock("omp_if.end"); + // Generate the branch (If-stmt) + CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock); + CGF.EmitBlock(ThenBlock); + } + } + void Done(CodeGenFunction &CGF) { + // Emit the rest of blocks/branches + CGF.EmitBranch(ContBlock); + CGF.EmitBlock(ContBlock, true); + } + void Exit(CodeGenFunction &CGF) override { + CGF.EmitRuntimeCall(ExitCallee, ExitArgs); + } +}; +} // anonymous namespace /// Get the GPU warp size. static llvm::Value *getNVPTXWarpSize(CodeGenFunction &CGF) { @@ -118,6 +167,7 @@ void CGOpenMPRuntimeNVPTX::emitGenericKernel(const OMPExecutableDirective &D, const RegionCodeGenTy &CodeGen) { EntryFunctionState EST; WorkerFunctionState WST(CGM); + Work.clear(); // Emit target region as a standalone region. class NVPTXPrePostActionTy : public PrePostActionTy { @@ -246,7 +296,10 @@ void CGOpenMPRuntimeNVPTX::emitWorkerLoop(CodeGenFunction &CGF, CGF.InitTempAlloca(ExecStatus, Bld.getInt8(/*C=*/0)); CGF.InitTempAlloca(WorkFn, llvm::Constant::getNullValue(CGF.Int8PtrTy)); - // TODO: Call into runtime to get parallel work. + llvm::Value *Args[] = {WorkFn.getPointer()}; + llvm::Value *Ret = CGF.EmitRuntimeCall( + createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_kernel_parallel), Args); + Bld.CreateStore(Bld.CreateZExt(Ret, CGF.Int8Ty), ExecStatus); // On termination condition (workid == 0), exit loop. llvm::Value *ShouldTerminate = @@ -261,10 +314,42 @@ void CGOpenMPRuntimeNVPTX::emitWorkerLoop(CodeGenFunction &CGF, // Signal start of parallel region. CGF.EmitBlock(ExecuteBB); - // TODO: Add parallel work. + + // Process work items: outlined parallel functions. + for (auto *W : Work) { + // Try to match this outlined function. + auto *ID = Bld.CreatePointerBitCastOrAddrSpaceCast(W, CGM.Int8PtrTy); + + llvm::Value *WorkFnMatch = + Bld.CreateICmpEQ(Bld.CreateLoad(WorkFn), ID, "work_match"); + + llvm::BasicBlock *ExecuteFNBB = CGF.createBasicBlock(".execute.fn"); + llvm::BasicBlock *CheckNextBB = CGF.createBasicBlock(".check.next"); + Bld.CreateCondBr(WorkFnMatch, ExecuteFNBB, CheckNextBB); + + // Execute this outlined function. + CGF.EmitBlock(ExecuteFNBB); + + // Insert call to work function. + // FIXME: Pass arguments to outlined function from master thread. + auto *Fn = cast<llvm::Function>(W); + Address ZeroAddr = + CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty, /*Name=*/".zero.addr"); + CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C=*/0)); + llvm::Value *FnArgs[] = {ZeroAddr.getPointer(), ZeroAddr.getPointer()}; + CGF.EmitCallOrInvoke(Fn, FnArgs); + + // Go to end of parallel region. + CGF.EmitBranch(TerminateBB); + + CGF.EmitBlock(CheckNextBB); + } // Signal end of parallel region. CGF.EmitBlock(TerminateBB); + CGF.EmitRuntimeCall( + createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_kernel_end_parallel), + llvm::None); CGF.EmitBranch(BarrierBB); // All active and inactive workers wait at a barrier after parallel region. @@ -296,10 +381,53 @@ CGOpenMPRuntimeNVPTX::createNVPTXRuntimeFunction(unsigned Function) { case OMPRTL_NVPTX__kmpc_kernel_deinit: { // Build void __kmpc_kernel_deinit(); llvm::FunctionType *FnTy = - llvm::FunctionType::get(CGM.VoidTy, {}, /*isVarArg*/ false); + llvm::FunctionType::get(CGM.VoidTy, llvm::None, /*isVarArg*/ false); RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_kernel_deinit"); break; } + case OMPRTL_NVPTX__kmpc_kernel_prepare_parallel: { + /// Build void __kmpc_kernel_prepare_parallel( + /// void *outlined_function); + llvm::Type *TypeParams[] = {CGM.Int8PtrTy}; + llvm::FunctionType *FnTy = + llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); + RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_kernel_prepare_parallel"); + break; + } + case OMPRTL_NVPTX__kmpc_kernel_parallel: { + /// Build bool __kmpc_kernel_parallel(void **outlined_function); + llvm::Type *TypeParams[] = {CGM.Int8PtrPtrTy}; + llvm::Type *RetTy = CGM.getTypes().ConvertType(CGM.getContext().BoolTy); + llvm::FunctionType *FnTy = + llvm::FunctionType::get(RetTy, TypeParams, /*isVarArg*/ false); + RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_kernel_parallel"); + break; + } + case OMPRTL_NVPTX__kmpc_kernel_end_parallel: { + /// Build void __kmpc_kernel_end_parallel(); + llvm::FunctionType *FnTy = + llvm::FunctionType::get(CGM.VoidTy, llvm::None, /*isVarArg*/ false); + RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_kernel_end_parallel"); + break; + } + case OMPRTL_NVPTX__kmpc_serialized_parallel: { + // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32 + // global_tid); + llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; + llvm::FunctionType *FnTy = + llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); + RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel"); + break; + } + case OMPRTL_NVPTX__kmpc_end_serialized_parallel: { + // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32 + // global_tid); + llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; + llvm::FunctionType *FnTy = + llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); + RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel"); + break; + } } return RTLFn; } @@ -362,9 +490,12 @@ llvm::Value *CGOpenMPRuntimeNVPTX::emitParallelOrTeamsOutlinedFunction( OutlinedFun = cast<llvm::Function>(OutlinedFunVal); OutlinedFun->removeFnAttr(llvm::Attribute::NoInline); OutlinedFun->addFnAttr(llvm::Attribute::AlwaysInline); - } else - llvm_unreachable("parallel directive is not yet supported for nvptx " - "backend."); + } else { + llvm::Value *OutlinedFunVal = + CGOpenMPRuntime::emitParallelOrTeamsOutlinedFunction( + D, ThreadIDVar, InnermostKind, CodeGen); + OutlinedFun = cast<llvm::Function>(OutlinedFunVal); + } return OutlinedFun; } @@ -387,3 +518,81 @@ void CGOpenMPRuntimeNVPTX::emitTeamsCall(CodeGenFunction &CGF, OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end()); CGF.EmitCallOrInvoke(OutlinedFn, OutlinedFnArgs); } + +void CGOpenMPRuntimeNVPTX::emitParallelCall( + CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *OutlinedFn, + ArrayRef<llvm::Value *> CapturedVars, const Expr *IfCond) { + if (!CGF.HaveInsertPoint()) + return; + + emitGenericParallelCall(CGF, Loc, OutlinedFn, CapturedVars, IfCond); +} + +void CGOpenMPRuntimeNVPTX::emitGenericParallelCall( + CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *OutlinedFn, + ArrayRef<llvm::Value *> CapturedVars, const Expr *IfCond) { + llvm::Function *Fn = cast<llvm::Function>(OutlinedFn); + + auto &&L0ParallelGen = [this, Fn, &CapturedVars](CodeGenFunction &CGF, + PrePostActionTy &) { + CGBuilderTy &Bld = CGF.Builder; + + // Prepare for parallel region. Indicate the outlined function. + llvm::Value *Args[] = {Bld.CreateBitOrPointerCast(Fn, CGM.Int8PtrTy)}; + CGF.EmitRuntimeCall( + createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_kernel_prepare_parallel), + Args); + + // Activate workers. This barrier is used by the master to signal + // work for the workers. + syncCTAThreads(CGF); + + // OpenMP [2.5, Parallel Construct, p.49] + // There is an implied barrier at the end of a parallel region. After the + // end of a parallel region, only the master thread of the team resumes + // execution of the enclosing task region. + // + // The master waits at this barrier until all workers are done. + syncCTAThreads(CGF); + + // Remember for post-processing in worker loop. + Work.push_back(Fn); + }; + + auto *RTLoc = emitUpdateLocation(CGF, Loc); + auto *ThreadID = getThreadID(CGF, Loc); + llvm::Value *Args[] = {RTLoc, ThreadID}; + + auto &&SeqGen = [this, Fn, &CapturedVars, &Args](CodeGenFunction &CGF, + PrePostActionTy &) { + auto &&CodeGen = [this, Fn, &CapturedVars, &Args](CodeGenFunction &CGF, + PrePostActionTy &Action) { + Action.Enter(CGF); + + llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs; + OutlinedFnArgs.push_back( + llvm::ConstantPointerNull::get(CGM.Int32Ty->getPointerTo())); + OutlinedFnArgs.push_back( + llvm::ConstantPointerNull::get(CGM.Int32Ty->getPointerTo())); + OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end()); + CGF.EmitCallOrInvoke(Fn, OutlinedFnArgs); + }; + + RegionCodeGenTy RCG(CodeGen); + NVPTXActionTy Action( + createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_serialized_parallel), + Args, + createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_end_serialized_parallel), + Args); + RCG.setAction(Action); + RCG(CGF); + }; + + if (IfCond) + emitOMPIfClause(CGF, IfCond, L0ParallelGen, SeqGen); + else { + CodeGenFunction::RunCleanupsScope Scope(CGF); + RegionCodeGenTy ThenRCG(L0ParallelGen); + ThenRCG(CGF); + } +} diff --git a/lib/CodeGen/CGOpenMPRuntimeNVPTX.h b/lib/CodeGen/CGOpenMPRuntimeNVPTX.h index 63a02965a5bd..4010b46a4cbd 100644 --- a/lib/CodeGen/CGOpenMPRuntimeNVPTX.h +++ b/lib/CodeGen/CGOpenMPRuntimeNVPTX.h @@ -25,6 +25,9 @@ namespace CodeGen { class CGOpenMPRuntimeNVPTX : public CGOpenMPRuntime { private: + // Parallel outlined function work for workers to execute. + llvm::SmallVector<llvm::Function *, 16> Work; + struct EntryFunctionState { llvm::BasicBlock *ExitBB = nullptr; }; @@ -100,6 +103,29 @@ private: bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) override; + /// \brief Emits code for parallel or serial call of the \a OutlinedFn with + /// variables captured in a record which address is stored in \a + /// CapturedStruct. + /// This call is for the Generic Execution Mode. + /// \param OutlinedFn Outlined function to be run in parallel threads. Type of + /// this function is void(*)(kmp_int32 *, kmp_int32, struct context_vars*). + /// \param CapturedVars A pointer to the record with the references to + /// variables used in \a OutlinedFn function. + /// \param IfCond Condition in the associated 'if' clause, if it was + /// specified, nullptr otherwise. + void emitGenericParallelCall(CodeGenFunction &CGF, SourceLocation Loc, + llvm::Value *OutlinedFn, + ArrayRef<llvm::Value *> CapturedVars, + const Expr *IfCond); + +protected: + /// \brief Get the function name of an outlined region. + // The name can be customized depending on the target. + // + StringRef getOutlinedHelperName() const override { + return "__omp_outlined__"; + } + public: explicit CGOpenMPRuntimeNVPTX(CodeGenModule &CGM); @@ -137,6 +163,20 @@ public: void emitTeamsCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, SourceLocation Loc, llvm::Value *OutlinedFn, ArrayRef<llvm::Value *> CapturedVars) override; + + /// \brief Emits code for parallel or serial call of the \a OutlinedFn with + /// variables captured in a record which address is stored in \a + /// CapturedStruct. + /// \param OutlinedFn Outlined function to be run in parallel threads. Type of + /// this function is void(*)(kmp_int32 *, kmp_int32, struct context_vars*). + /// \param CapturedVars A pointer to the record with the references to + /// variables used in \a OutlinedFn function. + /// \param IfCond Condition in the associated 'if' clause, if it was + /// specified, nullptr otherwise. + void emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, + llvm::Value *OutlinedFn, + ArrayRef<llvm::Value *> CapturedVars, + const Expr *IfCond) override; }; } // CodeGen namespace. diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp index 8d391f95d9f7..8370607db50f 100644 --- a/lib/CodeGen/CGStmt.cpp +++ b/lib/CodeGen/CGStmt.cpp @@ -330,6 +330,10 @@ void CodeGenFunction::EmitStmt(const Stmt *S) { EmitOMPTargetTeamsDistributeParallelForSimdDirective( cast<OMPTargetTeamsDistributeParallelForSimdDirective>(*S)); break; + case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass: + EmitOMPTargetTeamsDistributeSimdDirective( + cast<OMPTargetTeamsDistributeSimdDirective>(*S)); + break; } } diff --git a/lib/CodeGen/CGStmtOpenMP.cpp b/lib/CodeGen/CGStmtOpenMP.cpp index 386c4f0fe69c..39e1cdfdbe2a 100644 --- a/lib/CodeGen/CGStmtOpenMP.cpp +++ b/lib/CodeGen/CGStmtOpenMP.cpp @@ -2042,6 +2042,16 @@ void CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForSimdDirective( }); } +void CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDirective( + const OMPTargetTeamsDistributeSimdDirective &S) { + CGM.getOpenMPRuntime().emitInlinedDirective( + *this, OMPD_target_teams_distribute_simd, + [&S](CodeGenFunction &CGF, PrePostActionTy &) { + CGF.EmitStmt( + cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt()); + }); +} + /// \brief Emit a helper variable and return corresponding lvalue. static LValue EmitOMPHelperVar(CodeGenFunction &CGF, const DeclRefExpr *Helper) { diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 05522cd40024..586134023240 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -2701,6 +2701,8 @@ public: const OMPTargetTeamsDistributeParallelForDirective &S); void EmitOMPTargetTeamsDistributeParallelForSimdDirective( const OMPTargetTeamsDistributeParallelForSimdDirective &S); + void EmitOMPTargetTeamsDistributeSimdDirective( + const OMPTargetTeamsDistributeSimdDirective &S); /// Emit outlined function for the target directive. static std::pair<llvm::Function * /*OutlinedFn*/, diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index ab29d2dbb566..36005430ae4c 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -1243,9 +1243,15 @@ void CodeGenModule::EmitModuleLinkOptions() { SmallVector<clang::Module *, 16> Stack; // Seed the stack with imported modules. - for (Module *M : ImportedModules) + for (Module *M : ImportedModules) { + // Do not add any link flags when an implementation TU of a module imports + // a header of that same module. + if (M->getTopLevelModuleName() == getLangOpts().CurrentModule && + !getLangOpts().isCompilingModule()) + continue; if (Visited.insert(M).second) Stack.push_back(M); + } // Find all of the modules to import, making a little effort to prune // non-leaf modules. diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp index b5d90ea59a49..f7a8dd66c527 100644 --- a/lib/CodeGen/ItaniumCXXABI.cpp +++ b/lib/CodeGen/ItaniumCXXABI.cpp @@ -2272,7 +2272,21 @@ void ItaniumCXXABI::EmitThreadLocalInitFuncs( ArrayRef<llvm::Function *> CXXThreadLocalInits, ArrayRef<const VarDecl *> CXXThreadLocalInitVars) { llvm::Function *InitFunc = nullptr; - if (!CXXThreadLocalInits.empty()) { + + // Separate initializers into those with ordered (or partially-ordered) + // initialization and those with unordered initialization. + llvm::SmallVector<llvm::Function *, 8> OrderedInits; + llvm::SmallDenseMap<const VarDecl *, llvm::Function *> UnorderedInits; + for (unsigned I = 0; I != CXXThreadLocalInits.size(); ++I) { + if (isTemplateInstantiation( + CXXThreadLocalInitVars[I]->getTemplateSpecializationKind())) + UnorderedInits[CXXThreadLocalInitVars[I]->getCanonicalDecl()] = + CXXThreadLocalInits[I]; + else + OrderedInits.push_back(CXXThreadLocalInits[I]); + } + + if (!OrderedInits.empty()) { // Generate a guarded initialization function. llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false); @@ -2289,24 +2303,28 @@ void ItaniumCXXABI::EmitThreadLocalInitFuncs( CharUnits GuardAlign = CharUnits::One(); Guard->setAlignment(GuardAlign.getQuantity()); - CodeGenFunction(CGM) - .GenerateCXXGlobalInitFunc(InitFunc, CXXThreadLocalInits, - Address(Guard, GuardAlign)); + CodeGenFunction(CGM).GenerateCXXGlobalInitFunc(InitFunc, OrderedInits, + Address(Guard, GuardAlign)); // On Darwin platforms, use CXX_FAST_TLS calling convention. if (CGM.getTarget().getTriple().isOSDarwin()) { InitFunc->setCallingConv(llvm::CallingConv::CXX_FAST_TLS); InitFunc->addFnAttr(llvm::Attribute::NoUnwind); } } + + // Emit thread wrappers. for (const VarDecl *VD : CXXThreadLocals) { llvm::GlobalVariable *Var = cast<llvm::GlobalVariable>(CGM.GetGlobalValue(CGM.getMangledName(VD))); + llvm::Function *Wrapper = getOrCreateThreadLocalWrapper(VD, Var); // Some targets require that all access to thread local variables go through // the thread wrapper. This means that we cannot attempt to create a thread // wrapper or a thread helper. - if (isThreadWrapperReplaceable(VD, CGM) && !VD->hasDefinition()) + if (isThreadWrapperReplaceable(VD, CGM) && !VD->hasDefinition()) { + Wrapper->setLinkage(llvm::Function::ExternalLinkage); continue; + } // Mangle the name for the thread_local initialization function. SmallString<256> InitFnName; @@ -2322,18 +2340,21 @@ void ItaniumCXXABI::EmitThreadLocalInitFuncs( bool InitIsInitFunc = false; if (VD->hasDefinition()) { InitIsInitFunc = true; - if (InitFunc) + llvm::Function *InitFuncToUse = InitFunc; + if (isTemplateInstantiation(VD->getTemplateSpecializationKind())) + InitFuncToUse = UnorderedInits.lookup(VD->getCanonicalDecl()); + if (InitFuncToUse) Init = llvm::GlobalAlias::create(Var->getLinkage(), InitFnName.str(), - InitFunc); + InitFuncToUse); } else { // Emit a weak global function referring to the initialization function. // This function will not exist if the TU defining the thread_local // variable in question does not need any dynamic initialization for // its thread_local variables. llvm::FunctionType *FnTy = llvm::FunctionType::get(CGM.VoidTy, false); - Init = llvm::Function::Create( - FnTy, llvm::GlobalVariable::ExternalWeakLinkage, InitFnName.str(), - &CGM.getModule()); + Init = llvm::Function::Create(FnTy, + llvm::GlobalVariable::ExternalWeakLinkage, + InitFnName.str(), &CGM.getModule()); const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); CGM.SetLLVMFunctionAttributes(nullptr, FI, cast<llvm::Function>(Init)); } @@ -2341,7 +2362,6 @@ void ItaniumCXXABI::EmitThreadLocalInitFuncs( if (Init) Init->setVisibility(Var->getVisibility()); - llvm::Function *Wrapper = getOrCreateThreadLocalWrapper(VD, Var); llvm::LLVMContext &Context = CGM.getModule().getContext(); llvm::BasicBlock *Entry = llvm::BasicBlock::Create(Context, "", Wrapper); CGBuilderTy Builder(CGM, Entry); diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index 547e660ae09b..9bc9ae4f6a52 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -1531,7 +1531,7 @@ bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const { static const char *const AArch64LibDirs[] = {"/lib64", "/lib"}; static const char *const AArch64Triples[] = { "aarch64-none-linux-gnu", "aarch64-linux-gnu", "aarch64-linux-android", - "aarch64-redhat-linux"}; + "aarch64-redhat-linux", "aarch64-suse-linux"}; static const char *const AArch64beLibDirs[] = {"/lib"}; static const char *const AArch64beTriples[] = {"aarch64_be-none-linux-gnu", "aarch64_be-linux-gnu"}; diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index e267cdb2649f..b4a83347defa 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -6431,11 +6431,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, A->claim(); // We translate this by hand to the -cc1 argument, since nightly test uses - // it and developers have been trained to spell it with -mllvm. - if (StringRef(A->getValue(0)) == "-disable-llvm-passes") { - CmdArgs.push_back("-disable-llvm-passes"); - } else + // it and developers have been trained to spell it with -mllvm. Both + // spellings are now deprecated and should be removed. + if (StringRef(A->getValue(0)) == "-disable-llvm-optzns") { + CmdArgs.push_back("-disable-llvm-optzns"); + } else { A->render(Args, CmdArgs); + } } // With -save-temps, we want to save the unoptimized bitcode output from the diff --git a/lib/Format/ContinuationIndenter.cpp b/lib/Format/ContinuationIndenter.cpp index bf075ab6d53e..6bb6fb306035 100644 --- a/lib/Format/ContinuationIndenter.cpp +++ b/lib/Format/ContinuationIndenter.cpp @@ -1003,12 +1003,15 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State, // Generally inherit NoLineBreak from the current scope to nested scope. // However, don't do this for non-empty nested blocks, dict literals and // array literals as these follow different indentation rules. + const FormatToken *Previous = Current.getPreviousNonComment(); bool NoLineBreak = Current.Children.empty() && !Current.isOneOf(TT_DictLiteral, TT_ArrayInitializerLSquare) && (State.Stack.back().NoLineBreak || (Current.is(TT_TemplateOpener) && - State.Stack.back().ContainsUnwrappedBuilder)); + State.Stack.back().ContainsUnwrappedBuilder) || + (Current.is(tok::l_brace) && !Newline && Previous && + Previous->is(tok::comma))); State.Stack.push_back(ParenState(NewIndent, NewIndentLevel, LastSpace, AvoidBinPacking, NoLineBreak)); State.Stack.back().NestedBlockIndent = NestedBlockIndent; diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp index 17603ada11d1..4502c92499a7 100644 --- a/lib/Frontend/InitPreprocessor.cpp +++ b/lib/Frontend/InitPreprocessor.cpp @@ -286,12 +286,12 @@ static void DefineFastIntType(unsigned TypeWidth, bool IsSigned, /// Get the value the ATOMIC_*_LOCK_FREE macro should have for a type with /// the specified properties. -static const char *getLockFreeValue(unsigned TypeWidth, unsigned TypeAlign, - unsigned InlineWidth) { +static const char *getLockFreeValue(unsigned TypeWidth, unsigned InlineWidth) { // Fully-aligned, power-of-2 sizes no larger than the inline // width will be inlined as lock-free operations. - if (TypeWidth == TypeAlign && (TypeWidth & (TypeWidth - 1)) == 0 && - TypeWidth <= InlineWidth) + // Note: we do not need to check alignment since _Atomic(T) is always + // appropriately-aligned in clang. + if ((TypeWidth & (TypeWidth - 1)) == 0 && TypeWidth <= InlineWidth) return "2"; // "always lock free" // We cannot be certain what operations the lib calls might be // able to implement as lock-free on future processors. @@ -881,7 +881,6 @@ static void InitializePredefinedMacros(const TargetInfo &TI, #define DEFINE_LOCK_FREE_MACRO(TYPE, Type) \ Builder.defineMacro("__GCC_ATOMIC_" #TYPE "_LOCK_FREE", \ getLockFreeValue(TI.get##Type##Width(), \ - TI.get##Type##Align(), \ InlineWidthBits)); DEFINE_LOCK_FREE_MACRO(BOOL, Bool); DEFINE_LOCK_FREE_MACRO(CHAR, Char); @@ -894,7 +893,6 @@ static void InitializePredefinedMacros(const TargetInfo &TI, DEFINE_LOCK_FREE_MACRO(LLONG, LongLong); Builder.defineMacro("__GCC_ATOMIC_POINTER_LOCK_FREE", getLockFreeValue(TI.getPointerWidth(0), - TI.getPointerAlign(0), InlineWidthBits)); #undef DEFINE_LOCK_FREE_MACRO } diff --git a/lib/Headers/altivec.h b/lib/Headers/altivec.h index a8618816d5bb..a01d9d837ad1 100644 --- a/lib/Headers/altivec.h +++ b/lib/Headers/altivec.h @@ -7664,13 +7664,15 @@ vec_rlmi(vector unsigned long long __a, vector unsigned long long __b, static __inline__ vector unsigned int __ATTRS_o_ai vec_rlnm(vector unsigned int __a, vector unsigned int __b, vector unsigned int __c) { - return __builtin_altivec_vrlwnm(__a, __b) & __c; + vector unsigned int OneByte = { 0x8, 0x8, 0x8, 0x8 }; + return __builtin_altivec_vrlwnm(__a, ((__c << OneByte) | __b)); } static __inline__ vector unsigned long long __ATTRS_o_ai vec_rlnm(vector unsigned long long __a, vector unsigned long long __b, vector unsigned long long __c) { - return __builtin_altivec_vrldnm(__a, __b) & __c; + vector unsigned long long OneByte = { 0x8, 0x8 }; + return __builtin_altivec_vrldnm(__a, ((__c << OneByte) | __b)); } #endif diff --git a/lib/Index/IndexDecl.cpp b/lib/Index/IndexDecl.cpp index 1225391dc2a6..7d60aad3895d 100644 --- a/lib/Index/IndexDecl.cpp +++ b/lib/Index/IndexDecl.cpp @@ -46,10 +46,13 @@ public: } void handleDeclarator(const DeclaratorDecl *D, - const NamedDecl *Parent = nullptr) { + const NamedDecl *Parent = nullptr, + bool isIBType = false) { if (!Parent) Parent = D; - IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), Parent); + IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), Parent, + Parent->getLexicalDeclContext(), + /*isBase=*/false, isIBType); IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent); if (IndexCtx.shouldIndexFunctionLocalSymbols()) { // Only index parameters in definitions, parameters in declarations are @@ -92,8 +95,11 @@ public: if (!IndexCtx.handleDecl(D, (unsigned)SymbolRole::Dynamic, Relations)) return false; IndexCtx.indexTypeSourceInfo(D->getReturnTypeSourceInfo(), D); - for (const auto *I : D->parameters()) - handleDeclarator(I, D); + bool hasIBActionAndFirst = D->hasAttr<IBActionAttr>(); + for (const auto *I : D->parameters()) { + handleDeclarator(I, D, /*isIBType=*/hasIBActionAndFirst); + hasIBActionAndFirst = false; + } if (D->isThisDeclarationADefinition()) { const Stmt *Body = D->getBody(); @@ -283,11 +289,12 @@ public: bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) { const ObjCInterfaceDecl *C = D->getClassInterface(); - if (C) - TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D, - SymbolRoleSet(), SymbolRelation{ - (unsigned)SymbolRole::RelationExtendedBy, D - })); + if (!C) + return true; + TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D, SymbolRoleSet(), + SymbolRelation{ + (unsigned)SymbolRole::RelationExtendedBy, D + })); SourceLocation CategoryLoc = D->getCategoryNameLoc(); if (!CategoryLoc.isValid()) CategoryLoc = D->getLocation(); @@ -333,6 +340,9 @@ public: handleObjCMethod(MD, D); if (!IndexCtx.handleDecl(D)) return false; + if (IBOutletCollectionAttr *attr = D->getAttr<IBOutletCollectionAttr>()) + IndexCtx.indexTypeSourceInfo(attr->getInterfaceLoc(), D, + D->getLexicalDeclContext(), false, true); IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); return true; } diff --git a/lib/Index/IndexSymbol.cpp b/lib/Index/IndexSymbol.cpp index be847e762091..84984fce4dc7 100644 --- a/lib/Index/IndexSymbol.cpp +++ b/lib/Index/IndexSymbol.cpp @@ -152,10 +152,18 @@ SymbolInfo index::getSymbolInfo(const Decl *D) { Info.Lang = SymbolLanguage::ObjC; break; case Decl::ObjCMethod: - if (cast<ObjCMethodDecl>(D)->isInstanceMethod()) + if (cast<ObjCMethodDecl>(D)->isInstanceMethod()) { + const ObjCMethodDecl *MD = cast<ObjCMethodDecl>(D); Info.Kind = SymbolKind::InstanceMethod; - else + if (MD->isPropertyAccessor()) { + if (MD->param_size()) + Info.SubKind = SymbolSubKind::AccessorSetter; + else + Info.SubKind = SymbolSubKind::AccessorGetter; + } + } else { Info.Kind = SymbolKind::ClassMethod; + } Info.Lang = SymbolLanguage::ObjC; if (isUnitTest(cast<ObjCMethodDecl>(D))) Info.Properties |= (unsigned)SymbolProperty::UnitTest; @@ -289,6 +297,8 @@ void index::applyForEachSymbolRole(SymbolRoleSet Roles, APPLY_FOR_ROLE(RelationCalledBy); APPLY_FOR_ROLE(RelationExtendedBy); APPLY_FOR_ROLE(RelationAccessorOf); + APPLY_FOR_ROLE(RelationContainedBy); + APPLY_FOR_ROLE(RelationIBTypeOf); #undef APPLY_FOR_ROLE } @@ -317,6 +327,8 @@ void index::printSymbolRoles(SymbolRoleSet Roles, raw_ostream &OS) { case SymbolRole::RelationCalledBy: OS << "RelCall"; break; case SymbolRole::RelationExtendedBy: OS << "RelExt"; break; case SymbolRole::RelationAccessorOf: OS << "RelAcc"; break; + case SymbolRole::RelationContainedBy: OS << "RelCont"; break; + case SymbolRole::RelationIBTypeOf: OS << "RelIBType"; break; } }); } @@ -375,6 +387,8 @@ StringRef index::getSymbolSubKindString(SymbolSubKind K) { case SymbolSubKind::None: return "<none>"; case SymbolSubKind::CXXCopyConstructor: return "cxx-copy-ctor"; case SymbolSubKind::CXXMoveConstructor: return "cxx-move-ctor"; + case SymbolSubKind::AccessorGetter: return "acc-get"; + case SymbolSubKind::AccessorSetter: return "acc-set"; } llvm_unreachable("invalid symbol subkind"); } diff --git a/lib/Index/IndexTypeSourceInfo.cpp b/lib/Index/IndexTypeSourceInfo.cpp index 619a9a48befd..38bbb30fedf1 100644 --- a/lib/Index/IndexTypeSourceInfo.cpp +++ b/lib/Index/IndexTypeSourceInfo.cpp @@ -26,12 +26,16 @@ class TypeIndexer : public RecursiveASTVisitor<TypeIndexer> { public: TypeIndexer(IndexingContext &indexCtx, const NamedDecl *parent, - const DeclContext *DC, bool isBase) + const DeclContext *DC, bool isBase, bool isIBType) : IndexCtx(indexCtx), Parent(parent), ParentDC(DC), IsBase(isBase) { if (IsBase) { assert(Parent); Relations.emplace_back((unsigned)SymbolRole::RelationBaseOf, Parent); } + if (isIBType) { + assert(Parent); + Relations.emplace_back((unsigned)SymbolRole::RelationIBTypeOf, Parent); + } } bool shouldWalkTypesOfTypeLocs() const { return false; } @@ -93,13 +97,13 @@ public: bool VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) { return IndexCtx.handleReference(TL.getIFaceDecl(), TL.getNameLoc(), - Parent, ParentDC, SymbolRoleSet()); + Parent, ParentDC, SymbolRoleSet(), Relations); } bool VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) { for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i) { IndexCtx.handleReference(TL.getProtocol(i), TL.getProtocolLoc(i), - Parent, ParentDC, SymbolRoleSet()); + Parent, ParentDC, SymbolRoleSet(), Relations); } return true; } @@ -130,23 +134,25 @@ public: void IndexingContext::indexTypeSourceInfo(TypeSourceInfo *TInfo, const NamedDecl *Parent, const DeclContext *DC, - bool isBase) { + bool isBase, + bool isIBType) { if (!TInfo || TInfo->getTypeLoc().isNull()) return; - indexTypeLoc(TInfo->getTypeLoc(), Parent, DC, isBase); + indexTypeLoc(TInfo->getTypeLoc(), Parent, DC, isBase, isIBType); } void IndexingContext::indexTypeLoc(TypeLoc TL, const NamedDecl *Parent, const DeclContext *DC, - bool isBase) { + bool isBase, + bool isIBType) { if (TL.isNull()) return; if (!DC) DC = Parent->getLexicalDeclContext(); - TypeIndexer(*this, Parent, DC, isBase).TraverseTypeLoc(TL); + TypeIndexer(*this, Parent, DC, isBase, isIBType).TraverseTypeLoc(TL); } void IndexingContext::indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, diff --git a/lib/Index/IndexingContext.cpp b/lib/Index/IndexingContext.cpp index e623a495b47b..6dd6c0cfb28e 100644 --- a/lib/Index/IndexingContext.cpp +++ b/lib/Index/IndexingContext.cpp @@ -312,9 +312,20 @@ bool IndexingContext::handleDeclOccurrence(const Decl *D, SourceLocation Loc, Roles |= Rel.Roles; }; - if (!IsRef && Parent && !cast<DeclContext>(Parent)->isFunctionOrMethod()) { - addRelation(SymbolRelation{(unsigned)SymbolRole::RelationChildOf, Parent}); + if (Parent) { + if (IsRef) { + addRelation(SymbolRelation{ + (unsigned)SymbolRole::RelationContainedBy, + Parent + }); + } else if (!cast<DeclContext>(Parent)->isFunctionOrMethod()) { + addRelation(SymbolRelation{ + (unsigned)SymbolRole::RelationChildOf, + Parent + }); + } } + for (auto &Rel : Relations) { addRelation(SymbolRelation(Rel.Roles, Rel.RelatedSymbol->getCanonicalDecl())); diff --git a/lib/Index/IndexingContext.h b/lib/Index/IndexingContext.h index 600fc433b58d..dd1dd328cd44 100644 --- a/lib/Index/IndexingContext.h +++ b/lib/Index/IndexingContext.h @@ -85,11 +85,13 @@ public: void indexTypeSourceInfo(TypeSourceInfo *TInfo, const NamedDecl *Parent, const DeclContext *DC = nullptr, - bool isBase = false); + bool isBase = false, + bool isIBType = false); void indexTypeLoc(TypeLoc TL, const NamedDecl *Parent, const DeclContext *DC = nullptr, - bool isBase = false); + bool isBase = false, + bool isIBType = false); void indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, const NamedDecl *Parent, diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp index fa2a76ef47ca..c667f4bf2207 100644 --- a/lib/Lex/HeaderSearch.cpp +++ b/lib/Lex/HeaderSearch.cpp @@ -1092,13 +1092,51 @@ void HeaderSearch::MarkFileModuleHeader(const FileEntry *FE, } bool HeaderSearch::ShouldEnterIncludeFile(Preprocessor &PP, - const FileEntry *File, - bool isImport, Module *M) { + const FileEntry *File, bool isImport, + bool ModulesEnabled, Module *M) { ++NumIncluded; // Count # of attempted #includes. // Get information about this file. HeaderFileInfo &FileInfo = getFileInfo(File); + // FIXME: this is a workaround for the lack of proper modules-aware support + // for #import / #pragma once + auto TryEnterImported = [&](void) -> bool { + if (!ModulesEnabled) + return false; + // Modules with builtins are special; multiple modules use builtins as + // modular headers, example: + // + // module stddef { header "stddef.h" export * } + // + // After module map parsing, this expands to: + // + // module stddef { + // header "/path_to_builtin_dirs/stddef.h" + // textual "stddef.h" + // } + // + // It's common that libc++ and system modules will both define such + // submodules. Make sure cached results for a builtin header won't + // prevent other builtin modules to potentially enter the builtin header. + // Note that builtins are header guarded and the decision to actually + // enter them is postponed to the controlling macros logic below. + bool TryEnterHdr = false; + if (FileInfo.isCompilingModuleHeader && FileInfo.isModuleHeader) + TryEnterHdr = File->getDir() == ModMap.getBuiltinDir() && + ModuleMap::isBuiltinHeader( + llvm::sys::path::filename(File->getName())); + + // Textual headers can be #imported from different modules. Since ObjC + // headers find in the wild might rely only on #import and do not contain + // controlling macros, be conservative and only try to enter textual headers + // if such macro is present. + if (!FileInfo.isModuleHeader && + FileInfo.getControllingMacro(ExternalLookup)) + TryEnterHdr = true; + return TryEnterHdr; + }; + // If this is a #import directive, check that we have not already imported // this header. if (isImport) { @@ -1106,11 +1144,12 @@ bool HeaderSearch::ShouldEnterIncludeFile(Preprocessor &PP, FileInfo.isImport = true; // Has this already been #import'ed or #include'd? - if (FileInfo.NumIncludes) return false; + if (FileInfo.NumIncludes && !TryEnterImported()) + return false; } else { // Otherwise, if this is a #include of a file that was previously #import'd // or if this is the second #include of a #pragma once file, ignore it. - if (FileInfo.isImport) + if (FileInfo.isImport && !TryEnterImported()) return false; } diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp index 9d0f2eb2fa79..1488f624da64 100644 --- a/lib/Lex/ModuleMap.cpp +++ b/lib/Lex/ModuleMap.cpp @@ -144,7 +144,7 @@ static StringRef sanitizeFilenameAsIdentifier(StringRef Name, /// \brief Determine whether the given file name is the name of a builtin /// header, supplied by Clang to replace, override, or augment existing system /// headers. -static bool isBuiltinHeader(StringRef FileName) { +bool ModuleMap::isBuiltinHeader(StringRef FileName) { return llvm::StringSwitch<bool>(FileName) .Case("float.h", true) .Case("iso646.h", true) @@ -165,7 +165,7 @@ ModuleMap::findKnownHeader(const FileEntry *File) { HeadersMap::iterator Known = Headers.find(File); if (HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps && Known == Headers.end() && File->getDir() == BuiltinIncludeDir && - isBuiltinHeader(llvm::sys::path::filename(File->getName()))) { + ModuleMap::isBuiltinHeader(llvm::sys::path::filename(File->getName()))) { HeaderInfo.loadTopLevelSystemModules(); return Headers.find(File); } @@ -446,9 +446,19 @@ ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header, I = Known->second.begin(), E = Known->second.end(); I != E; ++I) { - if (I->isAvailable() && (!RequestingModule || - I->getModule()->isSubModuleOf(RequestingModule))) + + if (I->isAvailable() && + (!RequestingModule || + I->getModule()->isSubModuleOf(RequestingModule))) { + // When no requesting module is available, the caller is looking if a + // header is part a module by only looking into the module map. This is + // done by warn_uncovered_module_header checks; don't consider textual + // headers part of it in this mode, otherwise we get misleading warnings + // that a umbrella header is not including a textual header. + if (!RequestingModule && I->getRole() == ModuleMap::TextualHeader) + continue; return false; + } } return true; } @@ -1879,7 +1889,7 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken, // supplied by Clang. Find that builtin header. if (ActiveModule->IsSystem && LeadingToken != MMToken::UmbrellaKeyword && BuiltinIncludeDir && BuiltinIncludeDir != Directory && - isBuiltinHeader(Header.FileName)) { + ModuleMap::isBuiltinHeader(Header.FileName)) { SmallString<128> BuiltinPathName(BuiltinIncludeDir->getName()); llvm::sys::path::append(BuiltinPathName, Header.FileName); BuiltinFile = SourceMgr.getFileManager().getFile(BuiltinPathName); diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp index 9661e7b13f72..322c5809cd2c 100644 --- a/lib/Lex/PPDirectives.cpp +++ b/lib/Lex/PPDirectives.cpp @@ -1999,6 +1999,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, bool SkipHeader = false; if (ShouldEnter && !HeaderInfo.ShouldEnterIncludeFile(*this, File, isImport, + getLangOpts().Modules, SuggestedModule.getModule())) { ShouldEnter = false; SkipHeader = true; diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 833d93e4548a..2d320878014b 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -1591,7 +1591,7 @@ Parser::ParseSimpleDeclaration(unsigned Context, DS.complete(TheDecl); if (AnonRecord) { Decl* decls[] = {AnonRecord, TheDecl}; - return Actions.BuildDeclaratorGroup(decls, /*TypeMayContainAuto=*/false); + return Actions.BuildDeclaratorGroup(decls); } return Actions.ConvertDeclToDeclGroup(TheDecl); } @@ -2045,8 +2045,6 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes( } } - bool TypeContainsAuto = D.getDeclSpec().containsPlaceholderType(); - // Parse declarator '=' initializer. // If a '==' or '+=' is found, suggest a fixit to '='. if (isTokenEqualOrEqualTypo()) { @@ -2106,7 +2104,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes( Actions.ActOnInitializerError(ThisDecl); } else Actions.AddInitializerToDecl(ThisDecl, Init.get(), - /*DirectInit=*/false, TypeContainsAuto); + /*DirectInit=*/false); } } else if (Tok.is(tok::l_paren)) { // Parse C++ direct initializer: '(' expression-list ')' @@ -2149,7 +2147,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes( T.getCloseLocation(), Exprs); Actions.AddInitializerToDecl(ThisDecl, Initializer.get(), - /*DirectInit=*/true, TypeContainsAuto); + /*DirectInit=*/true); } } else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace) && (!CurParsedObjCImpl || !D.isFunctionDeclarator())) { @@ -2171,11 +2169,10 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes( if (Init.isInvalid()) { Actions.ActOnInitializerError(ThisDecl); } else - Actions.AddInitializerToDecl(ThisDecl, Init.get(), - /*DirectInit=*/true, TypeContainsAuto); + Actions.AddInitializerToDecl(ThisDecl, Init.get(), /*DirectInit=*/true); } else { - Actions.ActOnUninitializedDecl(ThisDecl, TypeContainsAuto); + Actions.ActOnUninitializedDecl(ThisDecl); } Actions.FinalizeDeclaration(ThisDecl); diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 4002b09d2bc4..3f1fe7e06fe3 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -710,7 +710,7 @@ Parser::ParseUsingDeclaration(unsigned Context, : "using declaration")) SkipUntil(tok::semi); - return Actions.BuildDeclaratorGroup(DeclsInGroup, /*MayContainAuto*/false); + return Actions.BuildDeclaratorGroup(DeclsInGroup); } Decl *Parser::ParseAliasDeclarationAfterDeclarator( @@ -2539,7 +2539,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, DS.complete(TheDecl); if (AnonRecord) { Decl* decls[] = {AnonRecord, TheDecl}; - return Actions.BuildDeclaratorGroup(decls, /*TypeMayContainAuto=*/false); + return Actions.BuildDeclaratorGroup(decls); } return Actions.ConvertDeclToDeclGroup(TheDecl); } @@ -2769,11 +2769,10 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, if (Init.isInvalid()) SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch); else if (ThisDecl) - Actions.AddInitializerToDecl(ThisDecl, Init.get(), EqualLoc.isInvalid(), - DS.containsPlaceholderType()); + Actions.AddInitializerToDecl(ThisDecl, Init.get(), EqualLoc.isInvalid()); } else if (ThisDecl && DS.getStorageClassSpec() == DeclSpec::SCS_static) // No initializer. - Actions.ActOnUninitializedDecl(ThisDecl, DS.containsPlaceholderType()); + Actions.ActOnUninitializedDecl(ThisDecl); if (ThisDecl) { if (!ThisDecl->isInvalidDecl()) { @@ -3545,7 +3544,7 @@ Parser::tryParseExceptionSpecification(bool Delayed, Actions.CheckBooleanCondition(KeywordLoc, NoexceptExpr.get()); NoexceptRange = SourceRange(KeywordLoc, T.getCloseLocation()); } else { - NoexceptType = EST_None; + NoexceptType = EST_BasicNoexcept; } } else { // There is no argument. diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 55b5ff498574..e7b6c6ff90b3 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -198,7 +198,7 @@ ExprResult Parser::ParseConstantExpression(TypeCastState isTypeCast) { // An expression is potentially evaluated unless it appears where an // integral constant expression is required (see 5.19) [...]. // C++98 and C++11 have no such rule, but this is only a defect in C++98. - EnterExpressionEvaluationContext Unevaluated(Actions, + EnterExpressionEvaluationContext ConstantEvaluated(Actions, Sema::ConstantEvaluated); ExprResult LHS(ParseCastExpression(false, false, isTypeCast)); diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index ca1b3b1ad01b..124266a42bd5 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -735,7 +735,7 @@ ExprResult Parser::TryParseLambdaExpression() { /// sometimes skip the initializers for init-captures and not fully /// populate \p Intro. This flag will be set to \c true if we do so. /// \return A DiagnosticID if it hit something unexpected. The location for -/// for the diagnostic is that of the current token. +/// the diagnostic is that of the current token. Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro, bool *SkippedInits) { typedef Optional<unsigned> DiagResult; @@ -1818,8 +1818,7 @@ Sema::ConditionResult Parser::ParseCXXCondition(StmtResult *InitStmt, } if (!InitExpr.isInvalid()) - Actions.AddInitializerToDecl(DeclOut, InitExpr.get(), !CopyInitialization, - DS.containsPlaceholderType()); + Actions.AddInitializerToDecl(DeclOut, InitExpr.get(), !CopyInitialization); else Actions.ActOnInitializerError(DeclOut); diff --git a/lib/Parse/ParseOpenMP.cpp b/lib/Parse/ParseOpenMP.cpp index f9ea8af00f50..cab7d3432db3 100644 --- a/lib/Parse/ParseOpenMP.cpp +++ b/lib/Parse/ParseOpenMP.cpp @@ -119,6 +119,7 @@ static OpenMPDirectiveKind ParseOpenMPDirectiveKind(Parser &P) { { OMPD_target, OMPD_teams, OMPD_target_teams }, { OMPD_target_teams, OMPD_distribute, OMPD_target_teams_distribute }, { OMPD_target_teams_distribute, OMPD_parallel, OMPD_target_teams_distribute_parallel }, + { OMPD_target_teams_distribute, OMPD_simd, OMPD_target_teams_distribute_simd }, { OMPD_target_teams_distribute_parallel, OMPD_for, OMPD_target_teams_distribute_parallel_for }, { OMPD_target_teams_distribute_parallel_for, OMPD_simd, OMPD_target_teams_distribute_parallel_for_simd } }; @@ -760,6 +761,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( case OMPD_target_teams_distribute: case OMPD_target_teams_distribute_parallel_for: case OMPD_target_teams_distribute_parallel_for_simd: + case OMPD_target_teams_distribute_simd: Diag(Tok, diag::err_omp_unexpected_directive) << getOpenMPDirectiveName(DKind); break; @@ -799,7 +801,8 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( /// 'teams distribute parallel for' | 'target teams' | /// 'target teams distribute' | /// 'target teams distribute parallel for' | -/// 'target teams distribute parallel for simd' {clause} +/// 'target teams distribute parallel for simd' | +/// 'target teams distribute simd' {clause} /// annot_pragma_openmp_end /// StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective( @@ -916,7 +919,8 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective( case OMPD_target_teams: case OMPD_target_teams_distribute: case OMPD_target_teams_distribute_parallel_for: - case OMPD_target_teams_distribute_parallel_for_simd: { + case OMPD_target_teams_distribute_parallel_for_simd: + case OMPD_target_teams_distribute_simd: { ConsumeToken(); // Parse directive name of the 'critical' directive if any. if (DKind == OMPD_critical) { diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index d8a4ea63153a..52e5194e6236 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -938,7 +938,7 @@ Parser::ParseDeclOrFunctionDefInternal(ParsedAttributesWithRange &attrs, Actions.setCurrentOpenCLExtensionForDecl(TheDecl); if (AnonRecord) { Decl* decls[] = {AnonRecord, TheDecl}; - return Actions.BuildDeclaratorGroup(decls, /*TypeMayContainAuto=*/false); + return Actions.BuildDeclaratorGroup(decls); } return Actions.ConvertDeclToDeclGroup(TheDecl); } @@ -1472,8 +1472,7 @@ Parser::TryAnnotateName(bool IsAddressOfOperand, return ANK_Error; if (Tok.isNot(tok::identifier) || SS.isInvalid()) { - if (TryAnnotateTypeOrScopeTokenAfterScopeSpec(EnteringContext, false, SS, - !WasScopeAnnotation)) + if (TryAnnotateTypeOrScopeTokenAfterScopeSpec(SS, !WasScopeAnnotation)) return ANK_Error; return ANK_Unresolved; } @@ -1486,8 +1485,7 @@ Parser::TryAnnotateName(bool IsAddressOfOperand, if (isTentativelyDeclared(Name)) { // Identifier has been tentatively declared, and thus cannot be resolved as // an expression. Fall back to annotating it as a type. - if (TryAnnotateTypeOrScopeTokenAfterScopeSpec(EnteringContext, false, SS, - !WasScopeAnnotation)) + if (TryAnnotateTypeOrScopeTokenAfterScopeSpec(SS, !WasScopeAnnotation)) return ANK_Error; return Tok.is(tok::annot_typename) ? ANK_Success : ANK_TentativeDecl; } @@ -1625,7 +1623,7 @@ bool Parser::TryKeywordIdentFallback(bool DisableKeyword) { /// /// Note that this routine emits an error if you call it with ::new or ::delete /// as the current tokens, so only call it in contexts where these are invalid. -bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext, bool NeedType) { +bool Parser::TryAnnotateTypeOrScopeToken() { assert((Tok.is(tok::identifier) || Tok.is(tok::coloncolon) || Tok.is(tok::kw_typename) || Tok.is(tok::annot_cxxscope) || Tok.is(tok::kw_decltype) || Tok.is(tok::annot_template_id) || @@ -1642,7 +1640,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext, bool NeedType) { if (getLangOpts().MSVCCompat && NextToken().is(tok::kw_typedef)) { Token TypedefToken; PP.Lex(TypedefToken); - bool Result = TryAnnotateTypeOrScopeToken(EnteringContext, NeedType); + bool Result = TryAnnotateTypeOrScopeToken(); PP.EnterToken(Tok); Tok = TypedefToken; if (!Result) @@ -1667,8 +1665,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext, bool NeedType) { Tok.is(tok::annot_decltype)) { // Attempt to recover by skipping the invalid 'typename' if (Tok.is(tok::annot_decltype) || - (!TryAnnotateTypeOrScopeToken(EnteringContext, NeedType) && - Tok.isAnnotation())) { + (!TryAnnotateTypeOrScopeToken() && Tok.isAnnotation())) { unsigned DiagID = diag::err_expected_qualified_after_typename; // MS compatibility: MSVC permits using known types with typename. // e.g. "typedef typename T* pointer_type" @@ -1728,33 +1725,24 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext, bool NeedType) { CXXScopeSpec SS; if (getLangOpts().CPlusPlus) - if (ParseOptionalCXXScopeSpecifier(SS, nullptr, EnteringContext)) + if (ParseOptionalCXXScopeSpecifier(SS, nullptr, /*EnteringContext*/false)) return true; - return TryAnnotateTypeOrScopeTokenAfterScopeSpec(EnteringContext, NeedType, - SS, !WasScopeAnnotation); + return TryAnnotateTypeOrScopeTokenAfterScopeSpec(SS, !WasScopeAnnotation); } /// \brief Try to annotate a type or scope token, having already parsed an /// optional scope specifier. \p IsNewScope should be \c true unless the scope /// specifier was extracted from an existing tok::annot_cxxscope annotation. -bool Parser::TryAnnotateTypeOrScopeTokenAfterScopeSpec(bool EnteringContext, - bool NeedType, - CXXScopeSpec &SS, +bool Parser::TryAnnotateTypeOrScopeTokenAfterScopeSpec(CXXScopeSpec &SS, bool IsNewScope) { if (Tok.is(tok::identifier)) { - IdentifierInfo *CorrectedII = nullptr; // Determine whether the identifier is a type name. if (ParsedType Ty = Actions.getTypeName( *Tok.getIdentifierInfo(), Tok.getLocation(), getCurScope(), &SS, false, NextToken().is(tok::period), nullptr, /*IsCtorOrDtorName=*/false, - /*NonTrivialTypeSourceInfo*/ true, - NeedType ? &CorrectedII : nullptr)) { - // A FixIt was applied as a result of typo correction - if (CorrectedII) - Tok.setIdentifierInfo(CorrectedII); - + /*NonTrivialTypeSourceInfo*/ true)) { SourceLocation BeginLoc = Tok.getLocation(); if (SS.isNotEmpty()) // it was a C++ qualified type name. BeginLoc = SS.getBeginLoc(); @@ -1803,11 +1791,11 @@ bool Parser::TryAnnotateTypeOrScopeTokenAfterScopeSpec(bool EnteringContext, UnqualifiedId TemplateName; TemplateName.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation()); bool MemberOfUnknownSpecialization; - if (TemplateNameKind TNK = - Actions.isTemplateName(getCurScope(), SS, - /*hasTemplateKeyword=*/false, TemplateName, - /*ObjectType=*/nullptr, EnteringContext, - Template, MemberOfUnknownSpecialization)) { + if (TemplateNameKind TNK = Actions.isTemplateName( + getCurScope(), SS, + /*hasTemplateKeyword=*/false, TemplateName, + /*ObjectType=*/nullptr, /*EnteringContext*/false, Template, + MemberOfUnknownSpecialization)) { // Consume the identifier. ConsumeToken(); if (AnnotateTemplateIdToken(Template, TNK, SS, SourceLocation(), diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp index 5953d020b4fb..a987a8ce0b31 100644 --- a/lib/Sema/AnalysisBasedWarnings.cpp +++ b/lib/Sema/AnalysisBasedWarnings.cpp @@ -56,6 +56,8 @@ using namespace clang; namespace { class UnreachableCodeHandler : public reachable_code::Callback { Sema &S; + SourceRange PreviousSilenceableCondVal; + public: UnreachableCodeHandler(Sema &s) : S(s) {} @@ -64,6 +66,14 @@ namespace { SourceRange SilenceableCondVal, SourceRange R1, SourceRange R2) override { + // Avoid reporting multiple unreachable code diagnostics that are + // triggered by the same conditional value. + if (PreviousSilenceableCondVal.isValid() && + SilenceableCondVal.isValid() && + PreviousSilenceableCondVal == SilenceableCondVal) + return; + PreviousSilenceableCondVal = SilenceableCondVal; + unsigned diag = diag::warn_unreachable; switch (UK) { case reachable_code::UK_Break: diff --git a/lib/Sema/SemaCoroutine.cpp b/lib/Sema/SemaCoroutine.cpp index 3109358df464..9814b4a84f29 100644 --- a/lib/Sema/SemaCoroutine.cpp +++ b/lib/Sema/SemaCoroutine.cpp @@ -187,7 +187,7 @@ static FunctionScopeInfo *checkCoroutineContext(Sema &S, SourceLocation Loc, S.Context.getTrivialTypeSourceInfo(T, Loc), SC_None); S.CheckVariableDeclarationType(ScopeInfo->CoroutinePromise); if (!ScopeInfo->CoroutinePromise->isInvalidDecl()) - S.ActOnUninitializedDecl(ScopeInfo->CoroutinePromise, false); + S.ActOnUninitializedDecl(ScopeInfo->CoroutinePromise); } return ScopeInfo; @@ -578,17 +578,6 @@ void Sema::CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body) { isa<CoyieldExpr>(First) ? 1 : 2); } - bool AnyCoawaits = false; - bool AnyCoyields = false; - for (auto *CoroutineStmt : Fn->CoroutineStmts) { - AnyCoawaits |= isa<CoawaitExpr>(CoroutineStmt); - AnyCoyields |= isa<CoyieldExpr>(CoroutineStmt); - } - - if (!AnyCoawaits && !AnyCoyields) - Diag(Fn->CoroutineStmts.front()->getLocStart(), - diag::ext_coroutine_without_co_await_co_yield); - SourceLocation Loc = FD->getLocation(); // Form a declaration statement for the promise declaration, so that AST diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index c32757565dd1..adcf2ee00e75 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -1044,7 +1044,8 @@ Corrected: } // We can have a type template here if we're classifying a template argument. - if (isa<TemplateDecl>(FirstDecl) && !isa<FunctionTemplateDecl>(FirstDecl)) + if (isa<TemplateDecl>(FirstDecl) && !isa<FunctionTemplateDecl>(FirstDecl) && + !isa<VarTemplateDecl>(FirstDecl)) return NameClassification::TypeTemplate( TemplateName(cast<TemplateDecl>(FirstDecl))); @@ -4503,7 +4504,7 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, // trivial in almost all cases, except if a union member has an in-class // initializer: // union { int n = 0; }; - ActOnUninitializedDecl(Anon, /*TypeMayContainAuto=*/false); + ActOnUninitializedDecl(Anon); } Anon->setImplicit(); @@ -6425,9 +6426,10 @@ NamedDecl *Sema::ActOnVariableDeclarator( } } - // Diagnose shadowed variables before filtering for scope. - if (D.getCXXScopeSpec().isEmpty()) - CheckShadow(S, NewVD, Previous); + // Find the shadowed declaration before filtering for scope. + NamedDecl *ShadowedDecl = D.getCXXScopeSpec().isEmpty() + ? getShadowedDeclaration(NewVD, Previous) + : nullptr; // Don't consider existing declarations that are in a different // scope and are out-of-semantic-context declarations (if the new @@ -6522,6 +6524,10 @@ NamedDecl *Sema::ActOnVariableDeclarator( } } + // Diagnose shadowed variables iff this isn't a redeclaration. + if (ShadowedDecl && !D.isRedeclaration()) + CheckShadow(NewVD, ShadowedDecl, Previous); + ProcessPragmaWeak(S, NewVD); // If this is the first declaration of an extern C variable, update @@ -6595,33 +6601,40 @@ static SourceLocation getCaptureLocation(const LambdaScopeInfo *LSI, return SourceLocation(); } -/// \brief Diagnose variable or built-in function shadowing. Implements -/// -Wshadow. -/// -/// This method is called whenever a VarDecl is added to a "useful" -/// scope. -/// -/// \param S the scope in which the shadowing name is being declared -/// \param R the lookup of the name -/// -void Sema::CheckShadow(Scope *S, VarDecl *D, const LookupResult& R) { +/// \brief Return the declaration shadowed by the given variable \p D, or null +/// if it doesn't shadow any declaration or shadowing warnings are disabled. +NamedDecl *Sema::getShadowedDeclaration(const VarDecl *D, + const LookupResult &R) { // Return if warning is ignored. if (Diags.isIgnored(diag::warn_decl_shadow, R.getNameLoc())) - return; + return nullptr; // Don't diagnose declarations at file scope. if (D->hasGlobalStorage()) - return; - - DeclContext *NewDC = D->getDeclContext(); + return nullptr; // Only diagnose if we're shadowing an unambiguous field or variable. if (R.getResultKind() != LookupResult::Found) - return; + return nullptr; - NamedDecl* ShadowedDecl = R.getFoundDecl(); - if (!isa<VarDecl>(ShadowedDecl) && !isa<FieldDecl>(ShadowedDecl)) - return; + NamedDecl *ShadowedDecl = R.getFoundDecl(); + return isa<VarDecl>(ShadowedDecl) || isa<FieldDecl>(ShadowedDecl) + ? ShadowedDecl + : nullptr; +} + +/// \brief Diagnose variable or built-in function shadowing. Implements +/// -Wshadow. +/// +/// This method is called whenever a VarDecl is added to a "useful" +/// scope. +/// +/// \param ShadowedDecl the declaration that is shadowed by the given variable +/// \param R the lookup of the name +/// +void Sema::CheckShadow(VarDecl *D, NamedDecl *ShadowedDecl, + const LookupResult &R) { + DeclContext *NewDC = D->getDeclContext(); if (FieldDecl *FD = dyn_cast<FieldDecl>(ShadowedDecl)) { // Fields are not shadowed by variables in C++ static methods. @@ -6732,7 +6745,8 @@ void Sema::CheckShadow(Scope *S, VarDecl *D) { LookupResult R(*this, D->getDeclName(), D->getLocation(), Sema::LookupOrdinaryName, Sema::ForRedeclaration); LookupName(R, S); - CheckShadow(S, D, R); + if (NamedDecl *ShadowedDecl = getShadowedDeclaration(D, R)) + CheckShadow(D, ShadowedDecl, R); } /// Check if 'E', which is an expression that is about to be modified, refers @@ -9782,8 +9796,7 @@ QualType Sema::deduceVarTypeFromInitializer(VarDecl *VDecl, /// AddInitializerToDecl - Adds the initializer Init to the /// declaration dcl. If DirectInit is true, this is C++ direct /// initialization rather than copy initialization. -void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, - bool DirectInit, bool TypeMayContainAuto) { +void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { // If there is no declaration, there was an error parsing it. Just ignore // the initializer. if (!RealDecl || RealDecl->isInvalidDecl()) { @@ -9808,7 +9821,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, } // C++11 [decl.spec.auto]p6. Deduce the type which 'auto' stands in for. - if (TypeMayContainAuto && VDecl->getType()->isUndeducedType()) { + if (VDecl->getType()->isUndeducedType()) { // Attempt typo correction early so that the type of the init expression can // be deduced based on the chosen correction if the original init contains a // TypoExpr. @@ -10280,8 +10293,7 @@ bool Sema::canInitializeWithParenthesizedList(QualType TargetType) { TargetType->getContainedAutoType(); } -void Sema::ActOnUninitializedDecl(Decl *RealDecl, - bool TypeMayContainAuto) { +void Sema::ActOnUninitializedDecl(Decl *RealDecl) { // If there is no declaration, there was an error parsing it. Just ignore it. if (!RealDecl) return; @@ -10297,7 +10309,7 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl, } // C++11 [dcl.spec.auto]p3 - if (TypeMayContainAuto && Type->getContainedAutoType()) { + if (Type->isUndeducedType()) { Diag(Var->getLocation(), diag::err_auto_var_requires_init) << Var->getDeclName() << Type; Var->setInvalidDecl(); @@ -11081,32 +11093,32 @@ Sema::DeclGroupPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS, } } - return BuildDeclaratorGroup(Decls, DS.containsPlaceholderType()); + return BuildDeclaratorGroup(Decls); } /// BuildDeclaratorGroup - convert a list of declarations into a declaration /// group, performing any necessary semantic checking. Sema::DeclGroupPtrTy -Sema::BuildDeclaratorGroup(MutableArrayRef<Decl *> Group, - bool TypeMayContainAuto) { - // C++0x [dcl.spec.auto]p7: - // If the type deduced for the template parameter U is not the same in each +Sema::BuildDeclaratorGroup(MutableArrayRef<Decl *> Group) { + // C++14 [dcl.spec.auto]p7: (DR1347) + // If the type that replaces the placeholder type is not the same in each // deduction, the program is ill-formed. - // FIXME: When initializer-list support is added, a distinction is needed - // between the deduced type U and the deduced type which 'auto' stands for. - // auto a = 0, b = { 1, 2, 3 }; - // is legal because the deduced type U is 'int' in both cases. - if (TypeMayContainAuto && Group.size() > 1) { + if (Group.size() > 1) { QualType Deduced; CanQualType DeducedCanon; VarDecl *DeducedDecl = nullptr; for (unsigned i = 0, e = Group.size(); i != e; ++i) { if (VarDecl *D = dyn_cast<VarDecl>(Group[i])) { AutoType *AT = D->getType()->getContainedAutoType(); + // FIXME: DR1265: if we have a function pointer declaration, we can have + // an 'auto' from a trailing return type. In that case, the return type + // must match the various other uses of 'auto'. + if (!AT) + continue; // Don't reissue diagnostics when instantiating a template. - if (AT && D->isInvalidDecl()) + if (D->isInvalidDecl()) break; - QualType U = AT ? AT->getDeducedType() : QualType(); + QualType U = AT->getDeducedType(); if (!U.isNull()) { CanQualType UCanon = Context.getCanonicalType(U); if (Deduced.isNull()) { diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index d172c951e749..b43e5b9e3278 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -1712,7 +1712,7 @@ Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc, DeclsInGroup.push_back(PDecl); } - return BuildDeclaratorGroup(DeclsInGroup, false); + return BuildDeclaratorGroup(DeclsInGroup); } Decl *Sema:: @@ -2019,7 +2019,7 @@ Sema::ActOnFinishObjCImplementation(Decl *ObjCImpDecl, ArrayRef<Decl *> Decls) { DeclsInGroup.push_back(ObjCImpDecl); - return BuildDeclaratorGroup(DeclsInGroup, false); + return BuildDeclaratorGroup(DeclsInGroup); } void Sema::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl, @@ -3043,7 +3043,7 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc, DeclsInGroup.push_back(IDecl); } - return BuildDeclaratorGroup(DeclsInGroup, false); + return BuildDeclaratorGroup(DeclsInGroup); } static bool tryMatchRecordTypes(ASTContext &Context, diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 1379440e8a03..b2fb33f53432 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -1504,14 +1504,12 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, SourceLocation PlacementLParen, MultiExprArg PlacementArgs, SourceLocation PlacementRParen, SourceRange TypeIdParens, Declarator &D, Expr *Initializer) { - bool TypeContainsAuto = D.getDeclSpec().containsPlaceholderType(); - Expr *ArraySize = nullptr; // If the specified type is an array, unwrap it and save the expression. if (D.getNumTypeObjects() > 0 && D.getTypeObject(0).Kind == DeclaratorChunk::Array) { - DeclaratorChunk &Chunk = D.getTypeObject(0); - if (TypeContainsAuto) + DeclaratorChunk &Chunk = D.getTypeObject(0); + if (D.getDeclSpec().containsPlaceholderType()) return ExprError(Diag(Chunk.Loc, diag::err_new_array_of_auto) << D.getSourceRange()); if (Chunk.Arr.hasStatic) @@ -1588,8 +1586,7 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, TInfo, ArraySize, DirectInitRange, - Initializer, - TypeContainsAuto); + Initializer); } static bool isLegalArrayNewInitializer(CXXNewExpr::InitializationStyle Style, @@ -1621,8 +1618,7 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, TypeSourceInfo *AllocTypeInfo, Expr *ArraySize, SourceRange DirectInitRange, - Expr *Initializer, - bool TypeMayContainAuto) { + Expr *Initializer) { SourceRange TypeRange = AllocTypeInfo->getTypeLoc().getSourceRange(); SourceLocation StartLoc = Range.getBegin(); @@ -1648,7 +1644,7 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, } // C++11 [dcl.spec.auto]p6. Deduce the type which 'auto' stands in for. - if (TypeMayContainAuto && AllocType->isUndeducedType()) { + if (AllocType->isUndeducedType()) { if (initStyle == CXXNewExpr::NoInit || NumInits == 0) return ExprError(Diag(StartLoc, diag::err_auto_new_requires_ctor_arg) << AllocType << TypeRange); diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp index edceb537df75..dcd19c8d817d 100644 --- a/lib/Sema/SemaOpenMP.cpp +++ b/lib/Sema/SemaOpenMP.cpp @@ -1089,7 +1089,7 @@ void Sema::EndOpenMPDSABlock(Stmt *CurDirective) { auto *VDPrivate = buildVarDecl( *this, DE->getExprLoc(), Type.getUnqualifiedType(), VD->getName(), VD->hasAttrs() ? &VD->getAttrs() : nullptr); - ActOnUninitializedDecl(VDPrivate, /*TypeMayContainAuto=*/false); + ActOnUninitializedDecl(VDPrivate); if (VDPrivate->isInvalidDecl()) continue; PrivateCopies.push_back(buildDeclRefExpr( @@ -1701,7 +1701,8 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) { case OMPD_teams_distribute_parallel_for: case OMPD_target_teams_distribute: case OMPD_target_teams_distribute_parallel_for: - case OMPD_target_teams_distribute_parallel_for_simd: { + case OMPD_target_teams_distribute_parallel_for_simd: + case OMPD_target_teams_distribute_simd: { QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1); QualType KmpInt32PtrTy = Context.getPointerType(KmpInt32Ty).withConst().withRestrict(); @@ -1761,8 +1762,7 @@ static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id, if (!WithInit) CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C, SourceRange())); S.CurContext->addHiddenDecl(CED); - S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false, - /*TypeMayContainAuto=*/true); + S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false); return CED; } @@ -2446,6 +2446,11 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( AllowedNameModifiers.push_back(OMPD_target); AllowedNameModifiers.push_back(OMPD_parallel); break; + case OMPD_target_teams_distribute_simd: + Res = ActOnOpenMPTargetTeamsDistributeSimdDirective( + ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); + AllowedNameModifiers.push_back(OMPD_target); + break; case OMPD_declare_target: case OMPD_end_declare_target: case OMPD_threadprivate: @@ -3970,33 +3975,32 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, // Lower bound variable, initialized with zero. VarDecl *LBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.lb"); LB = buildDeclRefExpr(SemaRef, LBDecl, VType, InitLoc); - SemaRef.AddInitializerToDecl( - LBDecl, SemaRef.ActOnIntegerConstant(InitLoc, 0).get(), - /*DirectInit*/ false, /*TypeMayContainAuto*/ false); + SemaRef.AddInitializerToDecl(LBDecl, + SemaRef.ActOnIntegerConstant(InitLoc, 0).get(), + /*DirectInit*/ false); // Upper bound variable, initialized with last iteration number. VarDecl *UBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.ub"); UB = buildDeclRefExpr(SemaRef, UBDecl, VType, InitLoc); SemaRef.AddInitializerToDecl(UBDecl, LastIteration.get(), - /*DirectInit*/ false, - /*TypeMayContainAuto*/ false); + /*DirectInit*/ false); // A 32-bit variable-flag where runtime returns 1 for the last iteration. // This will be used to implement clause 'lastprivate'. QualType Int32Ty = SemaRef.Context.getIntTypeForBitwidth(32, true); VarDecl *ILDecl = buildVarDecl(SemaRef, InitLoc, Int32Ty, ".omp.is_last"); IL = buildDeclRefExpr(SemaRef, ILDecl, Int32Ty, InitLoc); - SemaRef.AddInitializerToDecl( - ILDecl, SemaRef.ActOnIntegerConstant(InitLoc, 0).get(), - /*DirectInit*/ false, /*TypeMayContainAuto*/ false); + SemaRef.AddInitializerToDecl(ILDecl, + SemaRef.ActOnIntegerConstant(InitLoc, 0).get(), + /*DirectInit*/ false); // Stride variable returned by runtime (we initialize it to 1 by default). VarDecl *STDecl = buildVarDecl(SemaRef, InitLoc, StrideVType, ".omp.stride"); ST = buildDeclRefExpr(SemaRef, STDecl, StrideVType, InitLoc); - SemaRef.AddInitializerToDecl( - STDecl, SemaRef.ActOnIntegerConstant(InitLoc, 1).get(), - /*DirectInit*/ false, /*TypeMayContainAuto*/ false); + SemaRef.AddInitializerToDecl(STDecl, + SemaRef.ActOnIntegerConstant(InitLoc, 1).get(), + /*DirectInit*/ false); // Build expression: UB = min(UB, LastIteration) // It is necessary for CodeGen of directives with static scheduling. @@ -6428,6 +6432,39 @@ StmtResult Sema::ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective( Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); } +StmtResult Sema::ActOnOpenMPTargetTeamsDistributeSimdDirective( + ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc, + llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) { + if (!AStmt) + return StmtError(); + + auto *CS = cast<CapturedStmt>(AStmt); + // 1.2.2 OpenMP Language Terminology + // Structured block - An executable statement with a single entry at the + // top and a single exit at the bottom. + // The point of exit cannot be a branch out of the structured block. + // longjmp() and throw() must not violate the entry/exit criteria. + CS->getCapturedDecl()->setNothrow(); + + OMPLoopDirective::HelperExprs B; + // In presence of clause 'collapse' with number of loops, it will + // define the nested loops number. + auto NestedLoopCount = CheckOpenMPLoop( + OMPD_target_teams_distribute_simd, getCollapseNumberExpr(Clauses), + nullptr /*ordered not a clause on distribute*/, AStmt, *this, *DSAStack, + VarsWithImplicitDSA, B); + if (NestedLoopCount == 0) + return StmtError(); + + assert((CurContext->isDependentContext() || B.builtAll()) && + "omp target teams distribute simd loop exprs were not built"); + + getCurFunction()->setHasBranchProtectedScope(); + return OMPTargetTeamsDistributeSimdDirective::Create( + Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); +} + OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, @@ -7448,10 +7485,13 @@ OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList, // A list item cannot appear in both a map clause and a data-sharing // attribute clause on the same construct if (CurrDir == OMPD_target || CurrDir == OMPD_target_parallel || - CurrDir == OMPD_target_teams || + CurrDir == OMPD_target_teams || CurrDir == OMPD_target_teams_distribute || CurrDir == OMPD_target_teams_distribute_parallel_for || - CurrDir == OMPD_target_teams_distribute_parallel_for_simd) { + CurrDir == OMPD_target_teams_distribute_parallel_for_simd || + CurrDir == OMPD_target_teams_distribute_simd || + CurrDir == OMPD_target_parallel_for_simd || + CurrDir == OMPD_target_parallel_for) { OpenMPClauseKind ConflictKind; if (DSAStack->checkMappableExprComponentListsForDecl( VD, /*CurrentRegionOnly=*/true, @@ -7481,7 +7521,7 @@ OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList, Type = Type.getUnqualifiedType(); auto VDPrivate = buildVarDecl(*this, ELoc, Type, D->getName(), D->hasAttrs() ? &D->getAttrs() : nullptr); - ActOnUninitializedDecl(VDPrivate, /*TypeMayContainAuto=*/false); + ActOnUninitializedDecl(VDPrivate); if (VDPrivate->isInvalidDecl()) continue; auto VDPrivateRefExpr = buildDeclRefExpr( @@ -7709,10 +7749,13 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList, // A list item cannot appear in both a map clause and a data-sharing // attribute clause on the same construct if (CurrDir == OMPD_target || CurrDir == OMPD_target_parallel || - CurrDir == OMPD_target_teams || + CurrDir == OMPD_target_teams || CurrDir == OMPD_target_teams_distribute || CurrDir == OMPD_target_teams_distribute_parallel_for || - CurrDir == OMPD_target_teams_distribute_parallel_for_simd) { + CurrDir == OMPD_target_teams_distribute_parallel_for_simd || + CurrDir == OMPD_target_teams_distribute_simd || + CurrDir == OMPD_target_parallel_for_simd || + CurrDir == OMPD_target_parallel_for) { OpenMPClauseKind ConflictKind; if (DSAStack->checkMappableExprComponentListsForDecl( VD, /*CurrentRegionOnly=*/true, @@ -7784,7 +7827,7 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList, RefExpr->getExprLoc()); AddInitializerToDecl(VDPrivate, DefaultLvalueConversion(VDInitRefExpr).get(), - /*DirectInit=*/false, /*TypeMayContainAuto=*/false); + /*DirectInit=*/false); } if (VDPrivate->isInvalidDecl()) { if (IsImplicitClause) { @@ -8634,10 +8677,9 @@ OMPClause *Sema::ActOnOpenMPReductionClause( } } if (Init && DeclareReductionRef.isUnset()) { - AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false, - /*TypeMayContainAuto=*/false); + AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false); } else if (!Init) - ActOnUninitializedDecl(RHSVD, /*TypeMayContainAuto=*/false); + ActOnUninitializedDecl(RHSVD); if (RHSVD->isInvalidDecl()) continue; if (!RHSVD->hasInit() && DeclareReductionRef.isUnset()) { @@ -8886,7 +8928,7 @@ OMPClause *Sema::ActOnOpenMPLinearClause( else InitExpr = VD ? SimpleRefExpr : Ref; AddInitializerToDecl(Init, DefaultLvalueConversion(InitExpr).get(), - /*DirectInit=*/false, /*TypeMayContainAuto=*/false); + /*DirectInit=*/false); auto InitRef = buildDeclRefExpr(*this, Init, Type, ELoc); DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_linear, Ref); @@ -10231,7 +10273,8 @@ checkMappableExpressionList(Sema &SemaRef, DSAStackTy *DSAS, if ((DKind == OMPD_target || DKind == OMPD_target_teams || DKind == OMPD_target_teams_distribute || DKind == OMPD_target_teams_distribute_parallel_for || - DKind == OMPD_target_teams_distribute_parallel_for_simd) && VD) { + DKind == OMPD_target_teams_distribute_parallel_for_simd || + DKind == OMPD_target_teams_distribute_simd) && VD) { auto DVar = DSAS->getTopDSA(VD, false); if (isOpenMPPrivate(DVar.CKind)) { SemaRef.Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa) @@ -10963,7 +11006,7 @@ OMPClause *Sema::ActOnOpenMPUseDevicePtrClause(ArrayRef<Expr *> VarList, RefExpr->getExprLoc()); AddInitializerToDecl(VDPrivate, DefaultLvalueConversion(VDInitRefExpr).get(), - /*DirectInit=*/false, /*TypeMayContainAuto=*/false); + /*DirectInit=*/false); // If required, build a capture to implement the privatization initialized // with the current list item value. diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 41f4fa746fc6..afdae4ed6d7d 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -6596,7 +6596,9 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, Candidate.Function = MethodTmpl->getTemplatedDecl(); Candidate.Viable = false; Candidate.IsSurrogate = false; - Candidate.IgnoreObjectArgument = false; + Candidate.IgnoreObjectArgument = + cast<CXXMethodDecl>(Candidate.Function)->isStatic() || + ObjectType.isNull(); Candidate.ExplicitCallArguments = Args.size(); if (Result == TDK_NonDependentConversionFailure) Candidate.FailureKind = ovl_fail_bad_conversion; @@ -6658,7 +6660,11 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, Candidate.Function = FunctionTemplate->getTemplatedDecl(); Candidate.Viable = false; Candidate.IsSurrogate = false; - Candidate.IgnoreObjectArgument = false; + // Ignore the object argument if there is one, since we don't have an object + // type. + Candidate.IgnoreObjectArgument = + isa<CXXMethodDecl>(Candidate.Function) && + !isa<CXXConstructorDecl>(Candidate.Function); Candidate.ExplicitCallArguments = Args.size(); if (Result == TDK_NonDependentConversionFailure) Candidate.FailureKind = ovl_fail_bad_conversion; @@ -10490,56 +10496,42 @@ static void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand, // operation somehow. bool SuppressUserConversions = false; - const FunctionProtoType *Proto; - unsigned ArgIdx = 0; + unsigned ConvIdx = 0; + ArrayRef<QualType> ParamTypes; if (Cand->IsSurrogate) { QualType ConvType = Cand->Surrogate->getConversionType().getNonReferenceType(); if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>()) ConvType = ConvPtrType->getPointeeType(); - Proto = ConvType->getAs<FunctionProtoType>(); - ArgIdx = 1; + ParamTypes = ConvType->getAs<FunctionProtoType>()->getParamTypes(); + // Conversion 0 is 'this', which doesn't have a corresponding argument. + ConvIdx = 1; } else if (Cand->Function) { - Proto = Cand->Function->getType()->getAs<FunctionProtoType>(); + ParamTypes = + Cand->Function->getType()->getAs<FunctionProtoType>()->getParamTypes(); if (isa<CXXMethodDecl>(Cand->Function) && - !isa<CXXConstructorDecl>(Cand->Function)) - ArgIdx = 1; + !isa<CXXConstructorDecl>(Cand->Function)) { + // Conversion 0 is 'this', which doesn't have a corresponding argument. + ConvIdx = 1; + } } else { - // Builtin binary operator with a bad first conversion. + // Builtin operator. assert(ConvCount <= 3); - for (unsigned ConvIdx = (Cand->IgnoreObjectArgument ? 1 : 0); - ConvIdx != ConvCount; ++ConvIdx) { - if (Cand->Conversions[ConvIdx].isInitialized()) - continue; - if (Cand->BuiltinTypes.ParamTypes[ConvIdx]->isDependentType()) - Cand->Conversions[ConvIdx].setAsIdentityConversion( - Args[ConvIdx]->getType()); - else - Cand->Conversions[ConvIdx] = TryCopyInitialization( - S, Args[ConvIdx], Cand->BuiltinTypes.ParamTypes[ConvIdx], - SuppressUserConversions, - /*InOverloadResolution*/ true, - /*AllowObjCWritebackConversion=*/ - S.getLangOpts().ObjCAutoRefCount); - // FIXME: If the conversion is bad, try to fix it. - } - return; + ParamTypes = Cand->BuiltinTypes.ParamTypes; } // Fill in the rest of the conversions. - unsigned NumParams = Proto->getNumParams(); - for (unsigned ConvIdx = (Cand->IgnoreObjectArgument ? 1 : 0); - ConvIdx != ConvCount; ++ConvIdx, ++ArgIdx) { + for (unsigned ArgIdx = 0; ConvIdx != ConvCount; ++ConvIdx, ++ArgIdx) { if (Cand->Conversions[ConvIdx].isInitialized()) { - // Found the bad conversion. - } else if (ArgIdx < NumParams) { - if (Proto->getParamType(ArgIdx)->isDependentType()) + // We've already checked this conversion. + } else if (ArgIdx < ParamTypes.size()) { + if (ParamTypes[ArgIdx]->isDependentType()) Cand->Conversions[ConvIdx].setAsIdentityConversion( Args[ArgIdx]->getType()); else { Cand->Conversions[ConvIdx] = - TryCopyInitialization(S, Args[ArgIdx], Proto->getParamType(ArgIdx), + TryCopyInitialization(S, Args[ArgIdx], ParamTypes[ArgIdx], SuppressUserConversions, /*InOverloadResolution=*/true, /*AllowObjCWritebackConversion=*/ diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 50f0a22ff02b..a8832e9a1c54 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -1881,8 +1881,7 @@ static bool FinishForRangeVarDecl(Sema &SemaRef, VarDecl *Decl, Expr *Init, SemaRef.inferObjCARCLifetime(Decl)) Decl->setInvalidDecl(); - SemaRef.AddInitializerToDecl(Decl, Init, /*DirectInit=*/false, - /*TypeMayContainAuto=*/false); + SemaRef.AddInitializerToDecl(Decl, Init, /*DirectInit=*/false); SemaRef.FinalizeDeclaration(Decl); SemaRef.CurContext->addHiddenDecl(Decl); return false; @@ -2005,8 +2004,7 @@ StmtResult Sema::ActOnCXXForRangeStmt(Scope *S, SourceLocation ForLoc, // Claim the type doesn't contain auto: we've already done the checking. DeclGroupPtrTy RangeGroup = - BuildDeclaratorGroup(MutableArrayRef<Decl *>((Decl **)&RangeVar, 1), - /*TypeMayContainAuto=*/ false); + BuildDeclaratorGroup(MutableArrayRef<Decl *>((Decl **)&RangeVar, 1)); StmtResult RangeDecl = ActOnDeclStmt(RangeGroup, RangeLoc, RangeLoc); if (RangeDecl.isInvalid()) { LoopVar->setInvalidDecl(); @@ -2408,8 +2406,7 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation CoawaitLoc, // Attach *__begin as initializer for VD. Don't touch it if we're just // trying to determine whether this would be a valid range. if (!LoopVar->isInvalidDecl() && Kind != BFRK_Check) { - AddInitializerToDecl(LoopVar, DerefExpr.get(), /*DirectInit=*/false, - /*TypeMayContainAuto=*/true); + AddInitializerToDecl(LoopVar, DerefExpr.get(), /*DirectInit=*/false); if (LoopVar->isInvalidDecl()) NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin); } diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 795e6025d96f..8ad5b5951ea3 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -1224,9 +1224,17 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, } } + // If this is a templated friend in a dependent context we should not put it + // on the redecl chain. In some cases, the templated friend can be the most + // recent declaration tricking the template instantiator to make substitutions + // there. + // FIXME: Figure out how to combine with shouldLinkDependentDeclWithPrevious + bool ShouldAddRedecl + = !(TUK == TUK_Friend && CurContext->isDependentContext()); + CXXRecordDecl *NewClass = CXXRecordDecl::Create(Context, Kind, SemanticContext, KWLoc, NameLoc, Name, - PrevClassTemplate? + PrevClassTemplate && ShouldAddRedecl ? PrevClassTemplate->getTemplatedDecl() : nullptr, /*DelayTypeCreation=*/true); SetNestedNameSpecifier(NewClass, SS); @@ -1245,7 +1253,11 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, ClassTemplateDecl *NewTemplate = ClassTemplateDecl::Create(Context, SemanticContext, NameLoc, DeclarationName(Name), TemplateParams, - NewClass, PrevClassTemplate); + NewClass); + + if (ShouldAddRedecl) + NewTemplate->setPreviousDecl(PrevClassTemplate); + NewClass->setDescribedClassTemplate(NewTemplate); if (ModulePrivateLoc.isValid()) @@ -1653,6 +1665,7 @@ struct DependencyChecker : RecursiveASTVisitor<DependencyChecker> { typedef RecursiveASTVisitor<DependencyChecker> super; unsigned Depth; + bool FindLessThanDepth; // Whether we're looking for a use of a template parameter that makes the // overall construct type-dependent / a dependent type. This is strictly @@ -1663,25 +1676,16 @@ struct DependencyChecker : RecursiveASTVisitor<DependencyChecker> { bool Match; SourceLocation MatchLoc; - DependencyChecker(unsigned Depth, bool IgnoreNonTypeDependent) - : Depth(Depth), IgnoreNonTypeDependent(IgnoreNonTypeDependent), - Match(false) {} + DependencyChecker(unsigned Depth, bool IgnoreNonTypeDependent, + bool FindLessThanDepth = false) + : Depth(Depth), FindLessThanDepth(FindLessThanDepth), + IgnoreNonTypeDependent(IgnoreNonTypeDependent), Match(false) {} DependencyChecker(TemplateParameterList *Params, bool IgnoreNonTypeDependent) - : IgnoreNonTypeDependent(IgnoreNonTypeDependent), Match(false) { - NamedDecl *ND = Params->getParam(0); - if (TemplateTypeParmDecl *PD = dyn_cast<TemplateTypeParmDecl>(ND)) { - Depth = PD->getDepth(); - } else if (NonTypeTemplateParmDecl *PD = - dyn_cast<NonTypeTemplateParmDecl>(ND)) { - Depth = PD->getDepth(); - } else { - Depth = cast<TemplateTemplateParmDecl>(ND)->getDepth(); - } - } + : DependencyChecker(Params->getDepth(), IgnoreNonTypeDependent) {} bool Matches(unsigned ParmDepth, SourceLocation Loc = SourceLocation()) { - if (ParmDepth >= Depth) { + if (FindLessThanDepth ^ (ParmDepth >= Depth)) { Match = true; MatchLoc = Loc; return true; @@ -2336,15 +2340,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, // A<T, T> have identical types when A is declared as: // // template<typename T, typename U = T> struct A; - TemplateName CanonName = Context.getCanonicalTemplateName(Name); - CanonType = Context.getTemplateSpecializationType(CanonName, - Converted); - - // FIXME: CanonType is not actually the canonical type, and unfortunately - // it is a TemplateSpecializationType that we will never use again. - // In the future, we need to teach getTemplateSpecializationType to only - // build the canonical type and return that to us. - CanonType = Context.getCanonicalType(CanonType); + CanonType = Context.getCanonicalTemplateSpecializationType(Name, Converted); // This might work out to be a current instantiation, in which // case the canonical type needs to be the InjectedClassNameType. @@ -3452,7 +3448,7 @@ SubstDefaultTemplateArgument(Sema &SemaRef, SourceLocation TemplateLoc, SourceLocation RAngleLoc, TemplateTypeParmDecl *Param, - SmallVectorImpl<TemplateArgument> &Converted) { + SmallVectorImpl<TemplateArgument> &Converted) { TypeSourceInfo *ArgType = Param->getDefaultArgumentInfo(); // If the argument type is dependent, instantiate it now based @@ -5838,6 +5834,15 @@ Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg, return E; } +static bool isDependentOnOuter(NonTypeTemplateParmDecl *NTTP) { + if (NTTP->getDepth() == 0 || !NTTP->getType()->isDependentType()) + return false; + DependencyChecker Checker(NTTP->getDepth(), /*IgnoreNonTypeDependent*/ false, + /*FindLessThanDepth*/ true); + Checker.TraverseType(NTTP->getType()); + return Checker.Match; +} + /// \brief Match two template parameters within template parameter lists. static bool MatchTemplateParameterKind(Sema &S, NamedDecl *New, NamedDecl *Old, bool Complain, @@ -5894,11 +5899,10 @@ static bool MatchTemplateParameterKind(Sema &S, NamedDecl *New, NamedDecl *Old, // If we are matching a template template argument to a template // template parameter and one of the non-type template parameter types - // is dependent, then we must wait until template instantiation time - // to actually compare the arguments. + // is dependent on an outer template's parameter, then we must wait until + // template instantiation time to actually compare the arguments. if (Kind == Sema::TPL_TemplateTemplateArgumentMatch && - (OldNTTP->getType()->isDependentType() || - NewNTTP->getType()->isDependentType())) + (isDependentOnOuter(OldNTTP) || isDependentOnOuter(NewNTTP))) return true; if (!S.Context.hasSameType(OldNTTP->getType(), NewNTTP->getType())) { @@ -7785,6 +7789,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, Specialization->setTemplateKeywordLoc(TemplateLoc); Specialization->setBraceRange(SourceRange()); + bool PreviouslyDLLExported = Specialization->hasAttr<DLLExportAttr>(); if (Attr) ProcessDeclAttributeList(S, Specialization, Attr); @@ -7847,8 +7852,9 @@ Sema::ActOnExplicitInstantiation(Scope *S, // Fix a TSK_ImplicitInstantiation followed by a // TSK_ExplicitInstantiationDefinition - if (Old_TSK == TSK_ImplicitInstantiation && - Specialization->hasAttr<DLLExportAttr>() && + bool NewlyDLLExported = + !PreviouslyDLLExported && Specialization->hasAttr<DLLExportAttr>(); + if (Old_TSK == TSK_ImplicitInstantiation && NewlyDLLExported && (Context.getTargetInfo().getCXXABI().isMicrosoft() || Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment())) { // In the MS ABI, an explicit instantiation definition can add a dll diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index ba4a5b7bc0d7..9f744a1dc1b2 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -2264,9 +2264,6 @@ bool Sema::InstantiateInClassInitializer( if (auto *L = getASTMutationListener()) L->DefaultMemberInitializerInstantiated(Instantiation); - // Exit the scope of this instantiation. - SavedContext.pop(); - // Return true if the in-class initializer is still missing. return !Instantiation->getInClassInitializer(); } diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index d2a5e5cb5312..48d8b94af153 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1219,8 +1219,10 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { ClassTemplateDecl *Inst = ClassTemplateDecl::Create(SemaRef.Context, DC, D->getLocation(), - D->getIdentifier(), InstParams, RecordInst, - PrevClassTemplate); + D->getIdentifier(), InstParams, RecordInst); + assert(!(isFriend && Owner->isDependentContext())); + Inst->setPreviousDecl(PrevClassTemplate); + RecordInst->setDescribedClassTemplate(Inst); if (isFriend) { @@ -4085,7 +4087,6 @@ void Sema::InstantiateVariableInitializer( } if (!Init.isInvalid()) { - bool TypeMayContainAuto = true; Expr *InitExpr = Init.get(); if (Var->hasAttr<DLLImportAttr>() && @@ -4094,9 +4095,9 @@ void Sema::InstantiateVariableInitializer( // Do not dynamically initialize dllimport variables. } else if (InitExpr) { bool DirectInit = OldVar->isDirectInit(); - AddInitializerToDecl(Var, InitExpr, DirectInit, TypeMayContainAuto); + AddInitializerToDecl(Var, InitExpr, DirectInit); } else - ActOnUninitializedDecl(Var, TypeMayContainAuto); + ActOnUninitializedDecl(Var); } else { // FIXME: Not too happy about invalidating the declaration // because of a bogus initializer. @@ -4119,7 +4120,7 @@ void Sema::InstantiateVariableInitializer( if (Var->isCXXForRangeDecl()) return; - ActOnUninitializedDecl(Var, false); + ActOnUninitializedDecl(Var); } } diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index ae9a3ee790e1..29b21426790e 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -5263,7 +5263,7 @@ namespace { ParmVarDecl *Param = cast<ParmVarDecl>(FTI.Params[i].Param); TL.setParam(tpi++, Param); } - // FIXME: exception specs + TL.setExceptionSpecRange(FTI.getExceptionSpecRange()); } void VisitParenTypeLoc(ParenTypeLoc TL) { assert(Chunk.Kind == DeclaratorChunk::Paren); diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 66892936e573..c2aa3fef67c8 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -5023,6 +5023,7 @@ QualType TreeTransform<Derived>::TransformFunctionProtoType( NewTL.setLocalRangeBegin(TL.getLocalRangeBegin()); NewTL.setLParenLoc(TL.getLParenLoc()); NewTL.setRParenLoc(TL.getRParenLoc()); + NewTL.setExceptionSpecRange(TL.getExceptionSpecRange()); NewTL.setLocalRangeEnd(TL.getLocalRangeEnd()); for (unsigned i = 0, e = NewTL.getNumParams(); i != e; ++i) NewTL.setParam(i, ParamDecls[i]); @@ -7779,6 +7780,18 @@ StmtResult TreeTransform<Derived>:: return Res; } +template <typename Derived> +StmtResult +TreeTransform<Derived>::TransformOMPTargetTeamsDistributeSimdDirective( + OMPTargetTeamsDistributeSimdDirective *D) { + DeclarationNameInfo DirName; + getDerived().getSema().StartOpenMPDSABlock( + OMPD_target_teams_distribute_simd, DirName, nullptr, D->getLocStart()); + auto Res = getDerived().TransformOMPExecutableDirective(D); + getDerived().getSema().EndOpenMPDSABlock(Res.get()); + return Res; +} + //===----------------------------------------------------------------------===// // OpenMP clause transformation diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 7f890051e641..53224e2b493d 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -5990,6 +5990,8 @@ void TypeLocReader::VisitFunctionTypeLoc(FunctionTypeLoc TL) { TL.setLocalRangeBegin(ReadSourceLocation()); TL.setLParenLoc(ReadSourceLocation()); TL.setRParenLoc(ReadSourceLocation()); + TL.setExceptionSpecRange(SourceRange(Reader->ReadSourceLocation(*F, Record, Idx), + Reader->ReadSourceLocation(*F, Record, Idx))); TL.setLocalRangeEnd(ReadSourceLocation()); for (unsigned i = 0, e = TL.getNumParams(); i != e; ++i) { TL.setParam(i, Reader->ReadDeclAs<ParmVarDecl>(*F, Record, Idx)); diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 6e18b208a9ae..c6919193391b 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -748,6 +748,7 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { FD->IsExplicitlyDefaulted = Record.readInt(); FD->HasImplicitReturnZero = Record.readInt(); FD->IsConstexpr = Record.readInt(); + FD->UsesSEHTry = Record.readInt(); FD->HasSkippedBody = Record.readInt(); FD->IsLateTemplateParsed = Record.readInt(); FD->setCachedLinkage(Linkage(Record.readInt())); diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp index 19fac55664ae..686a69bbbcd2 100644 --- a/lib/Serialization/ASTReaderStmt.cpp +++ b/lib/Serialization/ASTReaderStmt.cpp @@ -2865,6 +2865,11 @@ void ASTStmtReader::VisitOMPTargetTeamsDistributeParallelForSimdDirective( VisitOMPLoopDirective(D); } +void ASTStmtReader::VisitOMPTargetTeamsDistributeSimdDirective( + OMPTargetTeamsDistributeSimdDirective *D) { + VisitOMPLoopDirective(D); +} + //===----------------------------------------------------------------------===// // ASTReader Implementation //===----------------------------------------------------------------------===// @@ -3651,6 +3656,14 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { break; } + case STMT_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD_DIRECTIVE: { + auto NumClauses = Record[ASTStmtReader::NumStmtFields]; + auto CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1]; + S = OMPTargetTeamsDistributeSimdDirective::CreateEmpty( + Context, NumClauses, CollapsedNum, Empty); + break; + } + case EXPR_CXX_OPERATOR_CALL: S = new (Context) CXXOperatorCallExpr(Context, Empty); break; diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 39e842db2baa..886523ea9431 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -629,6 +629,7 @@ void TypeLocWriter::VisitFunctionTypeLoc(FunctionTypeLoc TL) { Record.AddSourceLocation(TL.getLocalRangeBegin()); Record.AddSourceLocation(TL.getLParenLoc()); Record.AddSourceLocation(TL.getRParenLoc()); + Record.AddSourceRange(TL.getExceptionSpecRange()); Record.AddSourceLocation(TL.getLocalRangeEnd()); for (unsigned i = 0, e = TL.getNumParams(); i != e; ++i) Record.AddDeclRef(TL.getParam(i)); diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index 8e1480739a5f..d8466e9cbf3b 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -529,6 +529,7 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) { Record.push_back(D->IsExplicitlyDefaulted); Record.push_back(D->HasImplicitReturnZero); Record.push_back(D->IsConstexpr); + Record.push_back(D->UsesSEHTry); Record.push_back(D->HasSkippedBody); Record.push_back(D->IsLateTemplateParsed); Record.push_back(D->getLinkageInternal()); @@ -2032,6 +2033,7 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ExplicitlyDefaulted Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ImplicitReturnZero Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Constexpr + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // UsesSEHTry Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // SkippedBody Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // LateParsed Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Linkage diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp index 162b2bd25260..01fd98ceadb2 100644 --- a/lib/Serialization/ASTWriterStmt.cpp +++ b/lib/Serialization/ASTWriterStmt.cpp @@ -2563,6 +2563,12 @@ void ASTStmtWriter::VisitOMPTargetTeamsDistributeParallelForSimdDirective( STMT_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_DIRECTIVE; } +void ASTStmtWriter::VisitOMPTargetTeamsDistributeSimdDirective( + OMPTargetTeamsDistributeSimdDirective *D) { + VisitOMPLoopDirective(D); + Code = serialization::STMT_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD_DIRECTIVE; +} + //===----------------------------------------------------------------------===// // ASTWriter Implementation //===----------------------------------------------------------------------===// diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index 7e7e329dc4d7..d563f8e9eac0 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -515,8 +515,9 @@ void ExprEngine::ProcessInitializer(const CFGInitializer Init, Init = ASE->getBase()->IgnoreImplicit(); SVal LValue = State->getSVal(Init, stackFrame); - if (Optional<Loc> LValueLoc = LValue.getAs<Loc>()) - InitVal = State->getSVal(*LValueLoc); + if (!Field->getType()->isReferenceType()) + if (Optional<Loc> LValueLoc = LValue.getAs<Loc>()) + InitVal = State->getSVal(*LValueLoc); // If we fail to get the value for some reason, use a symbolic value. if (InitVal.isUnknownOrUndef()) { @@ -870,6 +871,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, case Stmt::OMPTargetTeamsDistributeDirectiveClass: case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass: case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass: + case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass: llvm_unreachable("Stmt should not be in analyzer evaluation loop"); case Stmt::ObjCSubscriptRefExprClass: diff --git a/lib/StaticAnalyzer/Core/SValBuilder.cpp b/lib/StaticAnalyzer/Core/SValBuilder.cpp index 10b0858b8488..ffaa0eda918a 100644 --- a/lib/StaticAnalyzer/Core/SValBuilder.cpp +++ b/lib/StaticAnalyzer/Core/SValBuilder.cpp @@ -218,6 +218,18 @@ SValBuilder::getDerivedRegionValueSymbolVal(SymbolRef parentSymbol, } DefinedSVal SValBuilder::getMemberPointer(const DeclaratorDecl* DD) { + assert(!DD || isa<CXXMethodDecl>(DD) || isa<FieldDecl>(DD)); + + if (auto *MD = dyn_cast_or_null<CXXMethodDecl>(DD)) { + // Sema treats pointers to static member functions as have function pointer + // type, so return a function pointer for the method. + // We don't need to play a similar trick for static member fields + // because these are represented as plain VarDecls and not FieldDecls + // in the AST. + if (MD->isStatic()) + return getFunctionPointer(MD); + } + return nonloc::PointerToMember(DD); } diff --git a/test/Analysis/initializer.cpp b/test/Analysis/initializer.cpp index b31c315ba524..09509271dae0 100644 --- a/test/Analysis/initializer.cpp +++ b/test/Analysis/initializer.cpp @@ -197,3 +197,10 @@ namespace ReferenceInitialization { } }; + +namespace PR31592 { +struct C { + C() : f("}") { } // no-crash + const char(&f)[2]; +}; +} diff --git a/test/Analysis/pointer-to-member.cpp b/test/Analysis/pointer-to-member.cpp index eef20627a132..039782b44b74 100644 --- a/test/Analysis/pointer-to-member.cpp +++ b/test/Analysis/pointer-to-member.cpp @@ -77,7 +77,8 @@ bool testDereferencing() { namespace testPointerToMemberFunction { struct A { virtual int foo() { return 1; } - int bar() { return 2; } + int bar() { return 2; } + int static staticMemberFunction(int p) { return p + 1; }; }; struct B : public A { @@ -111,11 +112,19 @@ namespace testPointerToMemberFunction { clang_analyzer_eval((APtr->*AFP)() == 3); // expected-warning{{TRUE}} } + + void testPointerToStaticMemberCall() { + int (*fPtr)(int) = &A::staticMemberFunction; + if (fPtr != 0) { // no-crash + clang_analyzer_eval(fPtr(2) == 3); // expected-warning{{TRUE}} + } + } } // end of testPointerToMemberFunction namespace namespace testPointerToMemberData { struct A { int i; + static int j; }; void testPointerToMemberData() { @@ -126,6 +135,13 @@ namespace testPointerToMemberData { a.*AMdPointer += 1; clang_analyzer_eval(a.i == 43); // expected-warning{{TRUE}} + + int *ptrToStaticField = &A::j; + if (ptrToStaticField != 0) { + *ptrToStaticField = 7; + clang_analyzer_eval(*ptrToStaticField == 7); // expected-warning{{TRUE}} + clang_analyzer_eval(A::j == 7); // expected-warning{{TRUE}} + } } } // end of testPointerToMemberData namespace diff --git a/test/Analysis/properties.m b/test/Analysis/properties.m index b1305341e5d4..235a9687821d 100644 --- a/test/Analysis/properties.m +++ b/test/Analysis/properties.m @@ -315,6 +315,32 @@ void testConsistencyAssign(Person *p) { } @end +__attribute__((objc_root_class)) +@interface ClassWithPrivatePropertyInClassExtensionWithProtocolShadowingCategory +@end + +@protocol HasStuff +@property (nonatomic, readonly) int stuffProperty; +@end + +@interface ClassWithPrivatePropertyInClassExtensionWithProtocolShadowingCategory (Private) +@property (nonatomic, readonly) int stuffProperty; +@end + +@interface ClassWithPrivatePropertyInClassExtensionWithProtocolShadowingCategory (Internal) <HasStuff> +@end + +@interface ClassWithPrivatePropertyInClassExtensionWithProtocolShadowingCategory() <HasStuff> +@end + +@implementation ClassWithPrivatePropertyInClassExtensionWithProtocolShadowingCategory +@synthesize stuffProperty = _stuffProperty; + +-(void)foo { + (void)self.stuffProperty; +} +@end + //------ // Setter ivar invalidation. //------ diff --git a/test/CXX/basic/basic.start/basic.start.init/p2.cpp b/test/CXX/basic/basic.start/basic.start.init/p2.cpp new file mode 100644 index 000000000000..36158210ac93 --- /dev/null +++ b/test/CXX/basic/basic.start/basic.start.init/p2.cpp @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -verify %s -pedantic-errors -std=c++11 +// RUN: %clang_cc1 -verify %s -pedantic-errors -std=c++14 +// expected-no-diagnostics + +struct foo_t { + union { + int i; + volatile int j; + } u; +}; + +__attribute__((__require_constant_initialization__)) +static const foo_t x = {{0}}; + +union foo_u { + int i; + volatile int j; +}; + +__attribute__((__require_constant_initialization__)) +static const foo_u y = {0}; diff --git a/test/CXX/drs/dr0xx.cpp b/test/CXX/drs/dr0xx.cpp index c988b6aba57e..055f40f98f66 100644 --- a/test/CXX/drs/dr0xx.cpp +++ b/test/CXX/drs/dr0xx.cpp @@ -1032,7 +1032,7 @@ namespace dr91 { // dr91: yes int k = f(U()); } -namespace dr92 { // dr92: 4.0 c++17 +namespace dr92 { // dr92: 4 c++17 void f() throw(int, float); // expected-error 0-1{{ISO C++1z does not allow}} expected-note 0-1{{use 'noexcept}} void (*p)() throw(int) = &f; // expected-error 0-1{{ISO C++1z does not allow}} expected-note 0-1{{use 'noexcept}} #if __cplusplus <= 201402L diff --git a/test/CXX/drs/dr12xx.cpp b/test/CXX/drs/dr12xx.cpp index 72d8d683ab7a..45b33f9d7daf 100644 --- a/test/CXX/drs/dr12xx.cpp +++ b/test/CXX/drs/dr12xx.cpp @@ -3,7 +3,7 @@ // RUN: %clang_cc1 -std=c++14 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -std=c++1z %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -namespace dr1213 { // dr1213: 4.0 +namespace dr1213 { // dr1213: 4 #if __cplusplus >= 201103L using T = int[3]; int &&r = T{}[1]; @@ -26,7 +26,7 @@ struct Derived : Base { }; } // dr1250 -namespace dr1295 { // dr1295: 4.0 +namespace dr1295 { // dr1295: 4 struct X { unsigned bitfield : 4; }; diff --git a/test/CXX/drs/dr13xx.cpp b/test/CXX/drs/dr13xx.cpp index 28e667f77f84..f35ead7b5e94 100644 --- a/test/CXX/drs/dr13xx.cpp +++ b/test/CXX/drs/dr13xx.cpp @@ -31,7 +31,7 @@ namespace dr1315 { // dr1315: partial // expected-error@-1 {{type of specialized non-type template argument depends on a template parameter of the partial specialization}} } -namespace dr1330 { // dr1330: 4.0 c++11 +namespace dr1330 { // dr1330: 4 c++11 // exception-specifications are parsed in a context where the class is complete. struct A { void f() throw(T) {} // expected-error 0-1{{C++1z}} expected-note 0-1{{noexcept}} @@ -175,7 +175,7 @@ namespace dr1359 { // dr1359: 3.5 #endif } -namespace dr1388 { // dr1388: 4.0 +namespace dr1388 { // dr1388: 4 template<typename A, typename ...T> void f(T..., A); // expected-note 1+{{candidate}} expected-error 0-1{{C++11}} template<typename ...T> void g(T..., int); // expected-note 1+{{candidate}} expected-error 0-1{{C++11}} template<typename ...T, typename A> void h(T..., A); // expected-note 1+{{candidate}} expected-error 0-1{{C++11}} diff --git a/test/CXX/drs/dr14xx.cpp b/test/CXX/drs/dr14xx.cpp index 9e724d918346..116437b1ab3c 100644 --- a/test/CXX/drs/dr14xx.cpp +++ b/test/CXX/drs/dr14xx.cpp @@ -343,7 +343,7 @@ namespace dr1490 { // dr1490: 3.7 c++11 std::initializer_list<char>{"abc"}; // expected-error {{expected unqualified-id}}} } // dr190 -namespace dr1495 { // dr1495: 4.0 +namespace dr1495 { // dr1495: 4 // Deduction succeeds in both directions. template<typename T, typename U> struct A {}; // expected-note {{template is declared here}} template<typename T, typename U> struct A<U, T> {}; // expected-error {{class template partial specialization is not more specialized}} diff --git a/test/CXX/drs/dr15xx.cpp b/test/CXX/drs/dr15xx.cpp index fb0d9334f6b6..a68928f727ef 100644 --- a/test/CXX/drs/dr15xx.cpp +++ b/test/CXX/drs/dr15xx.cpp @@ -3,7 +3,7 @@ // RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -std=c++1z -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -namespace dr1512 { // dr1512: 4.0 +namespace dr1512 { // dr1512: 4 void f(char *p) { if (p > 0) {} // expected-error {{ordered comparison between pointer and zero}} #if __cplusplus >= 201103L @@ -135,7 +135,7 @@ namespace dr1512 { // dr1512: 4.0 } } -namespace dr1518 { // dr1518: 4.0 +namespace dr1518 { // dr1518: 4 #if __cplusplus >= 201103L struct Z0 { // expected-note 0+ {{candidate}} explicit Z0() = default; // expected-note 0+ {{here}} diff --git a/test/CXX/drs/dr16xx.cpp b/test/CXX/drs/dr16xx.cpp index 02aa5f9909eb..c0b7c29e5dd1 100644 --- a/test/CXX/drs/dr16xx.cpp +++ b/test/CXX/drs/dr16xx.cpp @@ -86,7 +86,7 @@ namespace dr1645 { // dr1645: 3.9 #endif } -namespace dr1653 { // dr1653: 4.0 c++17 +namespace dr1653 { // dr1653: 4 c++17 void f(bool b) { ++b; b++; diff --git a/test/CXX/drs/dr18xx.cpp b/test/CXX/drs/dr18xx.cpp index 436bccc8e42e..e4ec199fcae8 100644 --- a/test/CXX/drs/dr18xx.cpp +++ b/test/CXX/drs/dr18xx.cpp @@ -7,7 +7,7 @@ // expected-no-diagnostics #endif -void dr1891() { // dr1891: 4.0 +void dr1891() { // dr1891: 4 #if __cplusplus >= 201103L int n; auto a = []{}; // expected-note 2{{candidate}} expected-note 2{{here}} diff --git a/test/CXX/drs/dr2xx.cpp b/test/CXX/drs/dr2xx.cpp index a9f0c8fcc999..68261f6c00f1 100644 --- a/test/CXX/drs/dr2xx.cpp +++ b/test/CXX/drs/dr2xx.cpp @@ -679,7 +679,7 @@ namespace dr258 { // dr258: yes } f; // expected-error {{abstract}} } -namespace dr259 { // dr259: 4.0 +namespace dr259 { // dr259: 4 template<typename T> struct A {}; template struct A<int>; // expected-note {{previous}} template struct A<int>; // expected-error {{duplicate explicit instantiation}} diff --git a/test/CXX/drs/dr5xx.cpp b/test/CXX/drs/dr5xx.cpp index f065128cd4bd..89e404f5fd6d 100644 --- a/test/CXX/drs/dr5xx.cpp +++ b/test/CXX/drs/dr5xx.cpp @@ -863,7 +863,7 @@ namespace dr580 { // dr580: partial // dr582: na -namespace dr583 { // dr583: 4.0 +namespace dr583 { // dr583: 4 // see n3624 int *p; bool b1 = p < 0; // expected-error {{ordered comparison between pointer and zero}} diff --git a/test/CXX/drs/dr6xx.cpp b/test/CXX/drs/dr6xx.cpp index 9dfcc7d6b464..8b9a69960767 100644 --- a/test/CXX/drs/dr6xx.cpp +++ b/test/CXX/drs/dr6xx.cpp @@ -142,7 +142,7 @@ namespace dr615 { // dr615: yes static int n = f(); } -namespace dr616 { // dr616: 4.0 +namespace dr616 { // dr616: 4 #if __cplusplus >= 201103L struct S { int n; } s; S f(); diff --git a/test/CodeGen/always_inline.c b/test/CodeGen/always_inline.c index 19d93d9db066..8e4a7c70b183 100644 --- a/test/CodeGen/always_inline.c +++ b/test/CodeGen/always_inline.c @@ -1,7 +1,7 @@ // RUN: %clang -emit-llvm -S -o %t %s // RUN: not grep '@f0' %t // RUN: not grep 'call ' %t -// RUN: %clang -mllvm -disable-llvm-passes -emit-llvm -S -o %t %s +// RUN: %clang -Xclang -disable-llvm-passes -emit-llvm -S -o %t %s // RUN: grep '@f0' %t | count 2 //static int f0() { diff --git a/test/CodeGen/arm_acle.c b/test/CodeGen/arm_acle.c index 0884394fbf19..b4f39bef1572 100644 --- a/test/CodeGen/arm_acle.c +++ b/test/CodeGen/arm_acle.c @@ -244,23 +244,23 @@ int16_t test_revsh(int16_t t) { } // ARM-LABEL: test_rbit -// AArch32: call i32 @llvm.arm.rbit -// AArch64: call i32 @llvm.aarch64.rbit.i32 +// AArch32: call i32 @llvm.bitreverse.i32 +// AArch64: call i32 @llvm.bitreverse.i32 uint32_t test_rbit(uint32_t t) { return __rbit(t); } // ARM-LABEL: test_rbitl -// AArch32: call i32 @llvm.arm.rbit -// AArch64: call i64 @llvm.aarch64.rbit.i64 +// AArch32: call i32 @llvm.bitreverse.i32 +// AArch64: call i64 @llvm.bitreverse.i64 long test_rbitl(long t) { return __rbitl(t); } // ARM-LABEL: test_rbitll -// AArch32: call i32 @llvm.arm.rbit -// AArch32: call i32 @llvm.arm.rbit -// AArch64: call i64 @llvm.aarch64.rbit.i64 +// AArch32: call i32 @llvm.bitreverse.i32 +// AArch32: call i32 @llvm.bitreverse.i32 +// AArch64: call i64 @llvm.bitreverse.i64 uint64_t test_rbitll(uint64_t t) { return __rbitll(t); } diff --git a/test/CodeGen/builtins-arm.c b/test/CodeGen/builtins-arm.c index a385bd27546a..0dc4c7dd7790 100644 --- a/test/CodeGen/builtins-arm.c +++ b/test/CodeGen/builtins-arm.c @@ -68,7 +68,7 @@ void test_barrier() { __builtin_arm_isb(3); //CHECK: call {{.*}} @llvm.arm.isb(i32 3) } -// CHECK: call {{.*}} @llvm.arm.rbit(i32 %a) +// CHECK: call {{.*}} @llvm.bitreverse.i32(i32 %a) unsigned rbit(unsigned a) { return __builtin_arm_rbit(a); diff --git a/test/CodeGen/builtins-arm64.c b/test/CodeGen/builtins-arm64.c index 20eb2abc9476..dc5fb6f31cff 100644 --- a/test/CodeGen/builtins-arm64.c +++ b/test/CodeGen/builtins-arm64.c @@ -10,12 +10,12 @@ void *tp (void) { // CHECK: call {{.*}} @llvm.thread.pointer() } -// CHECK: call {{.*}} @llvm.aarch64.rbit.i32(i32 %a) +// CHECK: call {{.*}} @llvm.bitreverse.i32(i32 %a) unsigned rbit(unsigned a) { return __builtin_arm_rbit(a); } -// CHECK: call {{.*}} @llvm.aarch64.rbit.i64(i64 %a) +// CHECK: call {{.*}} @llvm.bitreverse.i64(i64 %a) unsigned long long rbit64(unsigned long long a) { return __builtin_arm_rbit64(a); } diff --git a/test/CodeGen/builtins-ppc-p9vector.c b/test/CodeGen/builtins-ppc-p9vector.c index bd0ad182f15f..42316970d8da 100644 --- a/test/CodeGen/builtins-ppc-p9vector.c +++ b/test/CodeGen/builtins-ppc-p9vector.c @@ -868,20 +868,24 @@ vector unsigned long long test76(void) { return vec_rlmi(vula, vula, vula); } vector unsigned int test77(void) { +// CHECK-BE: %[[RES1:.+]] = shl <4 x i32 +// CHECK-BE: %[[RES2:.+]] = or <4 x i32> %[[RES1]] // CHECK-BE: @llvm.ppc.altivec.vrlwnm(<4 x i32 -// CHECK-BE: and <4 x i32 // CHECK-BE: ret <4 x i32> +// CHECK: %[[RES1:.+]] = shl <4 x i32 +// CHECK: %[[RES2:.+]] = or <4 x i32> %[[RES1]] // CHECK: @llvm.ppc.altivec.vrlwnm(<4 x i32 -// CHECK: and <4 x i32 // CHECK: ret <4 x i32> return vec_rlnm(vuia, vuia, vuia); } vector unsigned long long test78(void) { +// CHECK-BE: %[[RES1:.+]] = shl <2 x i64 +// CHECK-BE: %[[RES2:.+]] = or <2 x i64> %[[RES1]] // CHECK-BE: @llvm.ppc.altivec.vrldnm(<2 x i64 -// CHECK-BE: and <2 x i64 // CHECK-BE-NEXT: ret <2 x i64> +// CHECK: %[[RES1:.+]] = shl <2 x i64 +// CHECK: %[[RES2:.+]] = or <2 x i64> %[[RES1]] // CHECK: @llvm.ppc.altivec.vrldnm(<2 x i64 -// CHECK: and <2 x i64 // CHECK-NEXT: ret <2 x i64> return vec_rlnm(vula, vula, vula); } diff --git a/test/CodeGen/integer-overflow.c b/test/CodeGen/integer-overflow.c index 6a7c3e51ee1b..0b28bc5b8a2d 100644 --- a/test/CodeGen/integer-overflow.c +++ b/test/CodeGen/integer-overflow.c @@ -65,13 +65,37 @@ void test1() { // TRAPV: getelementptr inbounds i32, i32* // CATCH_UB: getelementptr inbounds i32, i32* - // PR9350: char increment never overflows. - extern volatile signed char PR9350; + // PR9350: char pre-increment never overflows. + extern volatile signed char PR9350_char_inc; // DEFAULT: add i8 {{.*}}, 1 // WRAPV: add i8 {{.*}}, 1 // TRAPV: add i8 {{.*}}, 1 // CATCH_UB: add i8 {{.*}}, 1 - ++PR9350; + ++PR9350_char_inc; + + // PR9350: char pre-decrement never overflows. + extern volatile signed char PR9350_char_dec; + // DEFAULT: add i8 {{.*}}, -1 + // WRAPV: add i8 {{.*}}, -1 + // TRAPV: add i8 {{.*}}, -1 + // CATCH_UB: add i8 {{.*}}, -1 + --PR9350_char_dec; + + // PR9350: short pre-increment never overflows. + extern volatile signed short PR9350_short_inc; + // DEFAULT: add i16 {{.*}}, 1 + // WRAPV: add i16 {{.*}}, 1 + // TRAPV: add i16 {{.*}}, 1 + // CATCH_UB: add i16 {{.*}}, 1 + ++PR9350_short_inc; + + // PR9350: short pre-decrement never overflows. + extern volatile signed short PR9350_short_dec; + // DEFAULT: add i16 {{.*}}, -1 + // WRAPV: add i16 {{.*}}, -1 + // TRAPV: add i16 {{.*}}, -1 + // CATCH_UB: add i16 {{.*}}, -1 + --PR9350_short_dec; // PR24256: don't instrument __builtin_frame_address. __builtin_frame_address(0 + 0); diff --git a/test/CodeGenCXX/cxx11-thread-local.cpp b/test/CodeGenCXX/cxx11-thread-local.cpp index f465cbdeea84..3231a76ba920 100644 --- a/test/CodeGenCXX/cxx11-thread-local.cpp +++ b/test/CodeGenCXX/cxx11-thread-local.cpp @@ -6,18 +6,18 @@ int f(); int g(); -// LINUX: @a = thread_local global i32 0 -// DARWIN: @a = internal thread_local global i32 0 +// LINUX-DAG: @a = thread_local global i32 0 +// DARWIN-DAG: @a = internal thread_local global i32 0 thread_local int a = f(); extern thread_local int b; -// CHECK: @c = global i32 0 +// CHECK-DAG: @c = global i32 0 int c = b; -// CHECK: @_ZL1d = internal thread_local global i32 0 +// CHECK-DAG: @_ZL1d = internal thread_local global i32 0 static thread_local int d = g(); struct U { static thread_local int m; }; -// LINUX: @_ZN1U1mE = thread_local global i32 0 -// DARWIN: @_ZN1U1mE = internal thread_local global i32 0 +// LINUX-DAG: @_ZN1U1mE = thread_local global i32 0 +// DARWIN-DAG: @_ZN1U1mE = internal thread_local global i32 0 thread_local int U::m = f(); namespace MismatchedInitType { @@ -35,37 +35,64 @@ namespace MismatchedInitType { template<typename T> struct V { static thread_local int m; }; template<typename T> thread_local int V<T>::m = g(); -// CHECK: @e = global i32 0 -int e = V<int>::m; +template<typename T> struct W { static thread_local int m; }; +template<typename T> thread_local int W<T>::m = 123; -// CHECK: @_ZN1VIiE1mE = linkonce_odr thread_local global i32 0 +struct Dtor { ~Dtor(); }; +template<typename T> struct X { static thread_local Dtor m; }; +template<typename T> thread_local Dtor X<T>::m; -// CHECK: @_ZZ1fvE1n = internal thread_local global i32 0 +// CHECK-DAG: @e = global +void *e = V<int>::m + W<int>::m + &X<int>::m; -// CHECK: @_ZGVZ1fvE1n = internal thread_local global i8 0 +template thread_local int V<float>::m; +template thread_local int W<float>::m; +template thread_local Dtor X<float>::m; -// CHECK: @_ZZ8tls_dtorvE1s = internal thread_local global -// CHECK: @_ZGVZ8tls_dtorvE1s = internal thread_local global i8 0 +extern template thread_local int V<char>::m; +extern template thread_local int W<char>::m; +extern template thread_local Dtor X<char>::m; -// CHECK: @_ZZ8tls_dtorvE1t = internal thread_local global -// CHECK: @_ZGVZ8tls_dtorvE1t = internal thread_local global i8 0 +void *e2 = V<char>::m + W<char>::m + &X<char>::m; -// CHECK: @_ZZ8tls_dtorvE1u = internal thread_local global -// CHECK: @_ZGVZ8tls_dtorvE1u = internal thread_local global i8 0 -// CHECK: @_ZGRZ8tls_dtorvE1u_ = internal thread_local global +// CHECK-DAG: @_ZN1VIiE1mE = linkonce_odr thread_local global i32 0 +// CHECK-DAG: @_ZN1WIiE1mE = linkonce_odr thread_local global i32 123 +// CHECK-DAG: @_ZN1XIiE1mE = linkonce_odr thread_local global {{.*}} +// CHECK-DAG: @_ZN1VIfE1mE = weak_odr thread_local global i32 0 +// CHECK-DAG: @_ZN1WIfE1mE = weak_odr thread_local global i32 123 +// CHECK-DAG: @_ZN1XIfE1mE = weak_odr thread_local global {{.*}} -// CHECK: @_ZGVN1VIiE1mE = linkonce_odr thread_local global i64 0 +// CHECK-DAG: @_ZZ1fvE1n = internal thread_local global i32 0 -// CHECK: @__tls_guard = internal thread_local global i8 0 +// CHECK-DAG: @_ZGVZ1fvE1n = internal thread_local global i8 0 -// CHECK: @llvm.global_ctors = appending global {{.*}} @[[GLOBAL_INIT:[^ ]*]] +// CHECK-DAG: @_ZZ8tls_dtorvE1s = internal thread_local global +// CHECK-DAG: @_ZGVZ8tls_dtorvE1s = internal thread_local global i8 0 -// LINUX: @_ZTH1a = alias void (), void ()* @__tls_init -// DARWIN: @_ZTH1a = internal alias void (), void ()* @__tls_init -// CHECK: @_ZTHL1d = internal alias void (), void ()* @__tls_init -// LINUX: @_ZTHN1U1mE = alias void (), void ()* @__tls_init -// DARWIN: @_ZTHN1U1mE = internal alias void (), void ()* @__tls_init -// CHECK: @_ZTHN1VIiE1mE = linkonce_odr alias void (), void ()* @__tls_init +// CHECK-DAG: @_ZZ8tls_dtorvE1t = internal thread_local global +// CHECK-DAG: @_ZGVZ8tls_dtorvE1t = internal thread_local global i8 0 + +// CHECK-DAG: @_ZZ8tls_dtorvE1u = internal thread_local global +// CHECK-DAG: @_ZGVZ8tls_dtorvE1u = internal thread_local global i8 0 +// CHECK-DAG: @_ZGRZ8tls_dtorvE1u_ = internal thread_local global + +// CHECK-DAG: @_ZGVN1VIiE1mE = linkonce_odr thread_local global i64 0 + +// CHECK-DAG: @__tls_guard = internal thread_local global i8 0 + +// CHECK-DAG: @llvm.global_ctors = appending global {{.*}} @[[GLOBAL_INIT:[^ ]*]] + +// LINUX-DAG: @_ZTH1a = alias void (), void ()* @__tls_init +// DARWIN-DAG: @_ZTH1a = internal alias void (), void ()* @__tls_init +// CHECK-DAG: @_ZTHL1d = internal alias void (), void ()* @__tls_init +// LINUX-DAG: @_ZTHN1U1mE = alias void (), void ()* @__tls_init +// DARWIN-DAG: @_ZTHN1U1mE = internal alias void (), void ()* @__tls_init +// CHECK-DAG: @_ZTHN1VIiE1mE = linkonce_odr alias void (), void ()* @[[V_M_INIT:[^, ]*]] +// CHECK-NOT: @_ZTHN1WIiE1mE = +// CHECK-DAG: @_ZTHN1XIiE1mE = linkonce_odr alias void (), void ()* @[[X_M_INIT:[^, ]*]] +// CHECK-DAG: @_ZTHN1VIfE1mE = weak_odr alias void (), void ()* @[[VF_M_INIT:[^, ]*]] +// CHECK-NOT: @_ZTHN1WIfE1mE = +// CHECK-DAG: @_ZTHN1XIfE1mE = weak_odr alias void (), void ()* @[[XF_M_INIT:[^, ]*]] // Individual variable initialization functions: @@ -118,7 +145,9 @@ int f() { // LINUX: call i32* @_ZTWN1VIiE1mE() // DARWIN: call cxx_fast_tlscc i32* @_ZTWN1VIiE1mE() // CHECK-NEXT: load i32, i32* %{{.*}}, align 4 -// CHECK-NEXT: store i32 %{{.*}}, i32* @e, align 4 +// LINUX: call {{.*}}* @_ZTWN1XIiE1mE() +// DARWIN: call cxx_fast_tlscc {{.*}}* @_ZTWN1XIiE1mE() +// CHECK: store {{.*}} @e // LINUX-LABEL: define weak_odr hidden i32* @_ZTWN1VIiE1mE() // DARWIN-LABEL: define weak_odr hidden cxx_fast_tlscc i32* @_ZTWN1VIiE1mE() @@ -126,6 +155,64 @@ int f() { // DARWIN: call cxx_fast_tlscc void @_ZTHN1VIiE1mE() // CHECK: ret i32* @_ZN1VIiE1mE +// LINUX-LABEL: define weak_odr hidden i32* @_ZTWN1WIiE1mE() +// DARWIN-LABEL: define weak_odr hidden cxx_fast_tlscc i32* @_ZTWN1WIiE1mE() +// CHECK-NOT: call +// CHECK: ret i32* @_ZN1WIiE1mE + +// LINUX-LABEL: define weak_odr hidden {{.*}}* @_ZTWN1XIiE1mE() +// DARWIN-LABEL: define weak_odr hidden cxx_fast_tlscc {{.*}}* @_ZTWN1XIiE1mE() +// LINUX: call void @_ZTHN1XIiE1mE() +// DARWIN: call cxx_fast_tlscc void @_ZTHN1XIiE1mE() +// CHECK: ret {{.*}}* @_ZN1XIiE1mE + +// CHECK: define internal {{.*}} @[[VF_M_INIT]]() +// LINUX-SAME: comdat($_ZN1VIfE1mE) +// DARWIN-NOT: comdat +// CHECK: load i8, i8* bitcast (i64* @_ZGVN1VIfE1mE to i8*) +// CHECK: %[[VF_M_INITIALIZED:.*]] = icmp eq i8 %{{.*}}, 0 +// CHECK: br i1 %[[VF_M_INITIALIZED]], +// need init: +// CHECK: call i32 @_Z1gv() +// CHECK: store i32 %{{.*}}, i32* @_ZN1VIfE1mE, align 4 +// CHECK: store i64 1, i64* @_ZGVN1VIfE1mE +// CHECK: br label + +// CHECK: define internal {{.*}} @[[XF_M_INIT]]() +// LINUX-SAME: comdat($_ZN1XIfE1mE) +// DARWIN-NOT: comdat +// CHECK: load i8, i8* bitcast (i64* @_ZGVN1XIfE1mE to i8*) +// CHECK: %[[XF_M_INITIALIZED:.*]] = icmp eq i8 %{{.*}}, 0 +// CHECK: br i1 %[[XF_M_INITIALIZED]], +// need init: +// LINUX: call {{.*}}__cxa_thread_atexit +// DARWIN: call {{.*}}_tlv_atexit +// CHECK: store i64 1, i64* @_ZGVN1XIfE1mE +// CHECK: br label + +// LINUX: declare i32 @__cxa_thread_atexit(void (i8*)*, i8*, i8*) +// DARWIN: declare i32 @_tlv_atexit(void (i8*)*, i8*, i8*) + +// DARWIN: declare cxx_fast_tlscc i32* @_ZTWN1VIcE1mE() +// LINUX: define weak_odr hidden i32* @_ZTWN1VIcE1mE() +// LINUX-NOT: comdat +// LINUX: br i1 icmp ne (void ()* @_ZTHN1VIcE1mE, +// LINUX: call void @_ZTHN1VIcE1mE() +// LINUX: ret i32* @_ZN1VIcE1mE + +// DARWIN: declare cxx_fast_tlscc i32* @_ZTWN1WIcE1mE() +// LINUX: define weak_odr hidden i32* @_ZTWN1WIcE1mE() +// LINUX-NOT: comdat +// LINUX: br i1 icmp ne (void ()* @_ZTHN1WIcE1mE, +// LINUX: call void @_ZTHN1WIcE1mE() +// LINUX: ret i32* @_ZN1WIcE1mE + +// DARWIN: declare cxx_fast_tlscc {{.*}}* @_ZTWN1XIcE1mE() +// LINUX: define weak_odr hidden {{.*}}* @_ZTWN1XIcE1mE() +// LINUX-NOT: comdat +// LINUX: br i1 icmp ne (void ()* @_ZTHN1XIcE1mE, +// LINUX: call void @_ZTHN1XIcE1mE() +// LINUX: ret {{.*}}* @_ZN1XIcE1mE struct S { S(); ~S(); }; struct T { ~T(); }; @@ -154,9 +241,6 @@ void tls_dtor() { static thread_local const S &u = S(); } -// LINUX: declare i32 @__cxa_thread_atexit(void (i8*)*, i8*, i8*) -// DARWIN: declare i32 @_tlv_atexit(void (i8*)*, i8*, i8*) - // CHECK: define {{.*}} @_Z7PR15991v( int PR15991() { thread_local int n; @@ -184,7 +268,9 @@ void set_anon_i() { // LINUX-LABEL: define internal i32* @_ZTWN12_GLOBAL__N_16anon_iE() // DARWIN-LABEL: define internal cxx_fast_tlscc i32* @_ZTWN12_GLOBAL__N_16anon_iE() -// CHECK: define {{.*}} @[[V_M_INIT:.*]]() +// CHECK: define internal {{.*}} @[[V_M_INIT]]() +// LINUX-SAME: comdat($_ZN1VIiE1mE) +// DARWIN-NOT: comdat // CHECK: load i8, i8* bitcast (i64* @_ZGVN1VIiE1mE to i8*) // CHECK: %[[V_M_INITIALIZED:.*]] = icmp eq i8 %{{.*}}, 0 // CHECK: br i1 %[[V_M_INITIALIZED]], @@ -194,6 +280,18 @@ void set_anon_i() { // CHECK: store i64 1, i64* @_ZGVN1VIiE1mE // CHECK: br label +// CHECK: define internal {{.*}} @[[X_M_INIT]]() +// LINUX-SAME: comdat($_ZN1XIiE1mE) +// DARWIN-NOT: comdat +// CHECK: load i8, i8* bitcast (i64* @_ZGVN1XIiE1mE to i8*) +// CHECK: %[[X_M_INITIALIZED:.*]] = icmp eq i8 %{{.*}}, 0 +// CHECK: br i1 %[[X_M_INITIALIZED]], +// need init: +// LINUX: call {{.*}}__cxa_thread_atexit +// DARWIN: call {{.*}}_tlv_atexit +// CHECK: store i64 1, i64* @_ZGVN1XIiE1mE +// CHECK: br label + // CHECK: define {{.*}}@[[GLOBAL_INIT:.*]]() // CHECK: call void @[[C_INIT]]() // CHECK: call void @[[E_INIT]]() @@ -205,10 +303,13 @@ void set_anon_i() { // CHECK: br i1 %[[NEED_TLS_INIT]], // init: // CHECK: store i8 1, i8* @__tls_guard +// CHECK-NOT: call void @[[V_M_INIT]]() // CHECK: call void @[[A_INIT]]() +// CHECK-NOT: call void @[[V_M_INIT]]() // CHECK: call void @[[D_INIT]]() +// CHECK-NOT: call void @[[V_M_INIT]]() // CHECK: call void @[[U_M_INIT]]() -// CHECK: call void @[[V_M_INIT]]() +// CHECK-NOT: call void @[[V_M_INIT]]() // LIUNX: define weak_odr hidden i32* @_ZTW1a() { diff --git a/test/CodeGenCXX/dllexport.cpp b/test/CodeGenCXX/dllexport.cpp index fe40bc0aac12..33e524cc9b01 100644 --- a/test/CodeGenCXX/dllexport.cpp +++ b/test/CodeGenCXX/dllexport.cpp @@ -732,13 +732,27 @@ USEMEMFUNC(ExplicitInstantiationDeclExportedDefTemplate<int>, f); // M32-DAG: define weak_odr dllexport x86_thiscallcc %struct.ExplicitInstantiationDeclExportedDefTemplate* @"\01??0?$ExplicitInstantiationDeclExportedDefTemplate@H@@QAE@XZ" // G32-DAG: define weak_odr x86_thiscallcc void @_ZN44ExplicitInstantiationDeclExportedDefTemplateIiE1fEv -template <typename T> struct ImplicitInstantiationExplicitInstantiationDefExportedTemplate { void f() {} }; +template <typename T> struct ImplicitInstantiationExportedExplicitInstantiationDefTemplate { virtual void f() {} }; +ImplicitInstantiationExportedExplicitInstantiationDefTemplate<int> ImplicitInstantiationExportedExplicitInstantiationDefTemplateInstance; +template struct __declspec(dllexport) ImplicitInstantiationExportedExplicitInstantiationDefTemplate<int>; +USEMEMFUNC(ImplicitInstantiationExportedExplicitInstantiationDefTemplate<int>, f); +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?f@?$ImplicitInstantiationExportedExplicitInstantiationDefTemplate@H@@UAEXXZ" +// G32-DAG: define weak_odr x86_thiscallcc void @_ZN61ImplicitInstantiationExportedExplicitInstantiationDefTemplateIiE1fEv + +template <typename T> struct __declspec(dllexport) ImplicitInstantiationExplicitInstantiationDefExportedTemplate { virtual void f() {} }; ImplicitInstantiationExplicitInstantiationDefExportedTemplate<int> ImplicitInstantiationExplicitInstantiationDefExportedTemplateInstance; -template class __declspec(dllexport) ImplicitInstantiationExplicitInstantiationDefExportedTemplate<int>; +template struct ImplicitInstantiationExplicitInstantiationDefExportedTemplate<int>; USEMEMFUNC(ImplicitInstantiationExplicitInstantiationDefExportedTemplate<int>, f); -// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?f@?$ImplicitInstantiationExplicitInstantiationDefExportedTemplate@H@@QAEXXZ" +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?f@?$ImplicitInstantiationExplicitInstantiationDefExportedTemplate@H@@UAEXXZ" // G32-DAG: define weak_odr x86_thiscallcc void @_ZN61ImplicitInstantiationExplicitInstantiationDefExportedTemplateIiE1fEv +template <typename T> struct __declspec(dllexport) ImplicitInstantiationExportedExplicitInstantiationDefExportedTemplate { virtual void f() {} }; +ImplicitInstantiationExportedExplicitInstantiationDefExportedTemplate<int> ImplicitInstantiationExportedExplicitInstantiationDefExportedTemplateInstance; +template struct __declspec(dllexport) ImplicitInstantiationExportedExplicitInstantiationDefExportedTemplate<int>; +USEMEMFUNC(ImplicitInstantiationExportedExplicitInstantiationDefExportedTemplate<int>, f); +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?f@?$ImplicitInstantiationExportedExplicitInstantiationDefExportedTemplate@H@@UAEXXZ" +// G32-DAG: define weak_odr x86_thiscallcc void @_ZN69ImplicitInstantiationExportedExplicitInstantiationDefExportedTemplateIiE1fEv + namespace { struct InternalLinkageType {}; } struct __declspec(dllexport) PR23308 { void f(InternalLinkageType*); diff --git a/test/CodeGenCXX/funcsig.cpp b/test/CodeGenCXX/funcsig.cpp index 2a6e641aec9c..16e5f7e1c9b1 100644 --- a/test/CodeGenCXX/funcsig.cpp +++ b/test/CodeGenCXX/funcsig.cpp @@ -1,22 +1,43 @@ -// RUN: %clang_cc1 -std=c++11 -triple i686-pc-win32 %s -fms-extensions -fno-rtti -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -triple i686-pc-win32 %s -fms-extensions -fno-rtti -emit-llvm -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-CXX +// RUN: %clang_cc1 -x c -triple i686-pc-win32 %s -fms-extensions -fno-rtti -emit-llvm -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-C // Similar to predefined-expr.cpp, but not as exhaustive, since it's basically // equivalent to __PRETTY_FUNCTION__. -extern "C" int printf(const char *, ...); +#ifdef __cplusplus +extern "C" +#endif +int printf(const char *, ...); -void freeFunc(int *, char) { +void funcNoProto() { + printf("__FUNCSIG__ %s\n\n", __FUNCSIG__); +} +// CHECK-C: @"\01??_C@_0BL@IHLLLCAO@void?5__cdecl?5funcNoProto?$CI?$CJ?$AA@" = linkonce_odr unnamed_addr constant [27 x i8] c"void __cdecl funcNoProto()\00" +// CHECK-CXX: @"\01??_C@_0BP@PJOECCJN@void?5__cdecl?5funcNoProto?$CIvoid?$CJ?$AA@" = linkonce_odr unnamed_addr constant [31 x i8] c"void __cdecl funcNoProto(void)\00" + +void funcNoParams(void) { + printf("__FUNCSIG__ %s\n\n", __FUNCSIG__); +} +// CHECK: @"\01??_C@_0CA@GBIDFNBN@void?5__cdecl?5funcNoParams?$CIvoid?$CJ?$AA@" = linkonce_odr unnamed_addr constant [32 x i8] c"void __cdecl funcNoParams(void)\00" + +void freeFunc(int *p, char c) { printf("__FUNCSIG__ %s\n\n", __FUNCSIG__); } // CHECK: @"\01??_C@_0CD@KLGMNNL@void?5__cdecl?5freeFunc?$CIint?5?$CK?0?5cha@" = linkonce_odr unnamed_addr constant [{{.*}} x i8] c"void __cdecl freeFunc(int *, char)\00" +#ifdef __cplusplus +void funcVarargs(...) { + printf("__FUNCSIG__ %s\n\n", __FUNCSIG__); +} +// CHECK-CXX: @"\01??_C@_0BO@BOBPLEKP@void?5__cdecl?5funcVarargs?$CI?4?4?4?$CJ?$AA@" = linkonce_odr unnamed_addr constant [30 x i8] c"void __cdecl funcVarargs(...)\00" + struct TopLevelClass { void topLevelMethod(int *, char); }; void TopLevelClass::topLevelMethod(int *, char) { printf("__FUNCSIG__ %s\n\n", __FUNCSIG__); } -// CHECK: @"\01??_C@_0DL@OBHNMDP@void?5__thiscall?5TopLevelClass?3?3t@" = linkonce_odr unnamed_addr constant [{{.*}} x i8] c"void __thiscall TopLevelClass::topLevelMethod(int *, char)\00" +// CHECK-CXX: @"\01??_C@_0DL@OBHNMDP@void?5__thiscall?5TopLevelClass?3?3t@" = linkonce_odr unnamed_addr constant [{{.*}} x i8] c"void __thiscall TopLevelClass::topLevelMethod(int *, char)\00" namespace NS { struct NamespacedClass { @@ -25,5 +46,6 @@ struct NamespacedClass { void NamespacedClass::namespacedMethod(int *, char) { printf("__FUNCSIG__ %s\n\n", __FUNCSIG__); } -// CHECK: @"\01??_C@_0ED@PFDKIEBA@void?5__thiscall?5NS?3?3NamespacedCl@" = linkonce_odr unnamed_addr constant [{{.*}} x i8] c"void __thiscall NS::NamespacedClass::namespacedMethod(int *, char)\00" +// CHECK-CXX: @"\01??_C@_0ED@PFDKIEBA@void?5__thiscall?5NS?3?3NamespacedCl@" = linkonce_odr unnamed_addr constant [{{.*}} x i8] c"void __thiscall NS::NamespacedClass::namespacedMethod(int *, char)\00" } +#endif diff --git a/test/CodeGenCXX/global-array-destruction.cpp b/test/CodeGenCXX/global-array-destruction.cpp index cb3524b3f0f0..1ae7b72838bd 100644 --- a/test/CodeGenCXX/global-array-destruction.cpp +++ b/test/CodeGenCXX/global-array-destruction.cpp @@ -39,7 +39,7 @@ struct T { T t[2][3] = { 1.0, 2, 3.0, 4, 5.0, 6, 7.0, 8, 9.0, 10, 11.0, 12 }; // CHECK: call {{.*}} @__cxa_atexit -// CHECK: getelementptr inbounds ({{.*}} bitcast {{.*}}* @t to %struct.T*), i64 6 +// CHECK: getelementptr inbounds ({{.*}} getelementptr inbounds ([2 x [3 x {{.*}}]], [2 x [3 x {{.*}}]]* @t, i32 0, i32 0, i32 0), i64 6) // CHECK: call void @_ZN1TD1Ev // CHECK: icmp eq {{.*}} @t // CHECK: br i1 {{.*}} @@ -47,9 +47,9 @@ T t[2][3] = { 1.0, 2, 3.0, 4, 5.0, 6, 7.0, 8, 9.0, 10, 11.0, 12 }; static T t2[2][3] = { 1.0, 2, 3.0, 4, 5.0, 6, 7.0, 8, 9.0, 10, 11.0, 12 }; // CHECK: call {{.*}} @__cxa_atexit -// CHECK: getelementptr inbounds ({{.*}} bitcast {{.*}}* @_ZL2t2 to %struct.T*), i64 6 +// CHECK: getelementptr inbounds ({{.*}} getelementptr inbounds ([2 x [3 x {{.*}}]], [2 x [3 x {{.*}}]]* @_ZL2t2, i32 0, i32 0, i32 0), i64 6) // CHECK: call void @_ZN1TD1Ev -// CHECK: icmp eq {{.*}} @_ZL2t +// CHECK: icmp eq {{.*}} @_ZL2t2 // CHECK: br i1 {{.*}} using U = T[2][3]; diff --git a/test/CodeGenCXX/pr31054.cpp b/test/CodeGenCXX/pr31054.cpp new file mode 100644 index 000000000000..33b17b9eafc8 --- /dev/null +++ b/test/CodeGenCXX/pr31054.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s + +struct A { ~A(); }; +void func() { + return; + static A k; +} + +// Test that we did not crash, by checking whether function was created. +// CHECK-LABEL: define void @_Z4funcv() #0 { +// CHECK: ret void +// CHECK: } diff --git a/test/Driver/Inputs/opensuse_42.2_aarch64_tree/usr/lib64/crt1.o b/test/Driver/Inputs/opensuse_42.2_aarch64_tree/usr/lib64/crt1.o new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/test/Driver/Inputs/opensuse_42.2_aarch64_tree/usr/lib64/crt1.o diff --git a/test/Driver/Inputs/opensuse_42.2_aarch64_tree/usr/lib64/crti.o b/test/Driver/Inputs/opensuse_42.2_aarch64_tree/usr/lib64/crti.o new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/test/Driver/Inputs/opensuse_42.2_aarch64_tree/usr/lib64/crti.o diff --git a/test/Driver/Inputs/opensuse_42.2_aarch64_tree/usr/lib64/crtn.o b/test/Driver/Inputs/opensuse_42.2_aarch64_tree/usr/lib64/crtn.o new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/test/Driver/Inputs/opensuse_42.2_aarch64_tree/usr/lib64/crtn.o diff --git a/test/Driver/Inputs/opensuse_42.2_aarch64_tree/usr/lib64/gcc/aarch64-suse-linux/4.8/crtbegin.o b/test/Driver/Inputs/opensuse_42.2_aarch64_tree/usr/lib64/gcc/aarch64-suse-linux/4.8/crtbegin.o new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/test/Driver/Inputs/opensuse_42.2_aarch64_tree/usr/lib64/gcc/aarch64-suse-linux/4.8/crtbegin.o diff --git a/test/Driver/Inputs/opensuse_42.2_aarch64_tree/usr/lib64/gcc/aarch64-suse-linux/4.8/crtend.o b/test/Driver/Inputs/opensuse_42.2_aarch64_tree/usr/lib64/gcc/aarch64-suse-linux/4.8/crtend.o new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/test/Driver/Inputs/opensuse_42.2_aarch64_tree/usr/lib64/gcc/aarch64-suse-linux/4.8/crtend.o diff --git a/test/Driver/cl-options.c b/test/Driver/cl-options.c index 25c9cd089e88..69238227c542 100644 --- a/test/Driver/cl-options.c +++ b/test/Driver/cl-options.c @@ -535,7 +535,7 @@ // RUN: -fno-ms-compatibility \ // RUN: -fms-extensions \ // RUN: -fno-ms-extensions \ -// RUN: -mllvm -disable-llvm-passes \ +// RUN: -Xclang -disable-llvm-passes \ // RUN: -resource-dir asdf \ // RUN: -resource-dir=asdf \ // RUN: -Wunused-variable \ diff --git a/test/Driver/disable-llvm.c b/test/Driver/disable-llvm.c new file mode 100644 index 000000000000..3ac6b9e91937 --- /dev/null +++ b/test/Driver/disable-llvm.c @@ -0,0 +1,22 @@ +// We support a CC1 option for disabling LLVM's passes. +// RUN: %clang -O2 -Xclang -disable-llvm-passes -### %s 2>&1 \ +// RUN: | FileCheck --check-prefix=DISABLED %s +// DISABLED: -cc1 +// DISABLED-NOT: "-mllvm" "-disable-llvm-passes" +// DISABLED: "-disable-llvm-passes" +// +// We also support two alternative spellings for historical reasons. +// RUN: %clang -O2 -Xclang -disable-llvm-optzns -### %s 2>&1 \ +// RUN: | FileCheck --check-prefix=DISABLED-LEGACY %s +// RUN: %clang -O2 -mllvm -disable-llvm-optzns -### %s 2>&1 \ +// RUN: | FileCheck --check-prefix=DISABLED-LEGACY %s +// DISABLED-LEGACY: -cc1 +// DISABLED-LEGACY-NOT: "-mllvm" "-disable-llvm-optzns" +// DISABLED-LEGACY: "-disable-llvm-optzns" +// +// The main flag shouldn't be specially handled when used with '-mllvm'. +// RUN: %clang -O2 -mllvm -disable-llvm-passes -### %s 2>&1 | FileCheck --check-prefix=MLLVM %s +// MLLVM: -cc1 +// MLLVM-NOT: -disable-llvm-passes +// MLLVM: "-mllvm" "-disable-llvm-passes" +// MLLVM-NOT: -disable-llvm-passes diff --git a/test/Driver/linux-ld.c b/test/Driver/linux-ld.c index 8fa71a507bf9..5d1001beb02c 100644 --- a/test/Driver/linux-ld.c +++ b/test/Driver/linux-ld.c @@ -618,6 +618,26 @@ // CHECK-SUSE-10-3-PPC64: "-L[[SYSROOT]]/lib/../lib64" // CHECK-SUSE-10-3-PPC64: "-L[[SYSROOT]]/usr/lib/../lib64" // +// Check openSuse Leap 42.2 on AArch64 +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: --target=arm64-unknown-linux-gnu \ +// RUN: --gcc-toolchain="" \ +// RUN: --sysroot=%S/Inputs/opensuse_42.2_aarch64_tree \ +// RUN: | FileCheck --check-prefix=CHECK-OPENSUSE-42-2-AARCH64 %s +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: --target=aarch64-unknown-linux-gnu \ +// RUN: --gcc-toolchain="" \ +// RUN: --sysroot=%S/Inputs/opensuse_42.2_aarch64_tree \ +// RUN: | FileCheck --check-prefix=CHECK-OPENSUSE-42-2-AARCH64 %s +// CHECK-OPENSUSE-42-2-AARCH64: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" +// CHECK-OPENSUSE-42-2-AARCH64: "{{.*}}/usr/lib64/gcc/aarch64-suse-linux/4.8/../../../../lib64{{/|\\\\}}crt1.o" +// CHECK-OPENSUSE-42-2-AARCH64: "{{.*}}/usr/lib64/gcc/aarch64-suse-linux/4.8/../../../../lib64{{/|\\\\}}crti.o" +// CHECK-OPENSUSE-42-2-AARCH64: "{{.*}}/usr/lib64/gcc/aarch64-suse-linux/4.8{{/|\\\\}}crtbegin.o" +// CHECK-OPENSUSE-42-2-AARCH64: "-L[[SYSROOT]]/usr/lib64/gcc/aarch64-suse-linux/4.8" +// CHECK-OPENSUSE-42-2-AARCH64: "-L[[SYSROOT]]/usr/lib64/gcc/aarch64-suse-linux/4.8/../../../../lib64" +// CHECK-OPENSUSE-42-2-AARCH64: "{{.*}}/usr/lib64/gcc/aarch64-suse-linux/4.8{{/|\\\\}}crtend.o" +// CHECK-OPENSUSE-42-2-AARCH64: "{{.*}}/usr/lib64/gcc/aarch64-suse-linux/4.8/../../../../lib64{{/|\\\\}}crtn.o" +// // Check dynamic-linker for different archs // RUN: %clang %s -### -o %t.o 2>&1 \ // RUN: --target=arm-linux-gnueabi \ diff --git a/test/Driver/x86-march.c b/test/Driver/x86-march.c index fd6e30b01593..b12bf405b0b0 100644 --- a/test/Driver/x86-march.c +++ b/test/Driver/x86-march.c @@ -36,6 +36,30 @@ // RUN: | FileCheck %s -check-prefix=broadwell // broadwell: "-target-cpu" "broadwell" // +// RUN: %clang -target x86_64-unknown-unknown -c -### %s -march=skylake 2>&1 \ +// RUN: | FileCheck %s -check-prefix=skylake +// skylake: "-target-cpu" "skylake" +// +// RUN: %clang -target x86_64-unknown-unknown -c -### %s -march=skylake-avx512 2>&1 \ +// RUN: | FileCheck %s -check-prefix=skylake-avx512 +// skylake-avx512: "-target-cpu" "skylake-avx512" +// +// RUN: %clang -target x86_64-unknown-unknown -c -### %s -march=skx 2>&1 \ +// RUN: | FileCheck %s -check-prefix=skx +// skx: "-target-cpu" "skx" +// +// RUN: %clang -target x86_64-unknown-unknown -c -### %s -march=knl 2>&1 \ +// RUN: | FileCheck %s -check-prefix=knl +// knl: "-target-cpu" "knl" +// +// RUN: %clang -target x86_64-unknown-unknown -c -### %s -march=cannonlake 2>&1 \ +// RUN: | FileCheck %s -check-prefix=cannonlake +// cannonlake: "-target-cpu" "cannonlake" +// +// RUN: %clang -target x86_64-unknown-unknown -c -### %s -march=lakemont 2>&1 \ +// RUN: | FileCheck %s -check-prefix=lakemont +// lakemont: "-target-cpu" "lakemont" +// // RUN: %clang -target x86_64-unknown-unknown -c -### %s -march=bonnell 2>&1 \ // RUN: | FileCheck %s -check-prefix=bonnell // bonnell: "-target-cpu" "bonnell" @@ -103,3 +127,7 @@ // RUN: %clang -target x86_64-unknown-unknown -c -### %s -march=btver2 2>&1 \ // RUN: | FileCheck %s -check-prefix=btver2 // btver2: "-target-cpu" "btver2" +// +// RUN: %clang -target x86_64-unknown-unknown -c -### %s -march=znver1 2>&1 \ +// RUN: | FileCheck %s -check-prefix=znver1 +// znver1: "-target-cpu" "znver1" diff --git a/test/Frontend/x86-target-cpu.c b/test/Frontend/x86-target-cpu.c index 769c40a016e3..4e0db5568a93 100644 --- a/test/Frontend/x86-target-cpu.c +++ b/test/Frontend/x86-target-cpu.c @@ -9,6 +9,11 @@ // RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-cpu ivybridge -verify %s // RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-cpu haswell -verify %s // RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-cpu broadwell -verify %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-cpu skylake -verify %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-cpu skylake-avx512 -verify %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-cpu skx -verify %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-cpu cannonlake -verify %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-cpu knl -verify %s // RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-cpu bonnell -verify %s // RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-cpu silvermont -verify %s // RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-cpu k8 -verify %s @@ -26,5 +31,6 @@ // RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-cpu bdver4 -verify %s // RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-cpu btver1 -verify %s // RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-cpu btver2 -verify %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-cpu znver1 -verify %s // // expected-no-diagnostics diff --git a/test/Index/Core/designated-inits.c b/test/Index/Core/designated-inits.c index 24bb9a9acdf0..a31cb95a4b82 100644 --- a/test/Index/Core/designated-inits.c +++ b/test/Index/Core/designated-inits.c @@ -5,7 +5,7 @@ struct MyStruct { }; enum { - MyValToSet; + MyValToSet }; // CHECK: [[@LINE+1]]:14 | struct/C | MyStruct | @@ -20,7 +20,7 @@ const struct MyStruct _MyStruct[] [0] = { [0][0] = { [0] = { - // CHECK: [[@LINE+2]]:14 | field/C | myfield | {{.*}} | Ref | + // CHECK: [[@LINE+2]]:14 | field/C | myfield | {{.*}} | Ref,RelCont | // CHECK: [[@LINE+1]]:24 | enumerator/C | MyValToSet | .myfield = MyValToSet, // CHECK-NOT: | field/C | myfield | diff --git a/test/Index/Core/index-source.cpp b/test/Index/Core/index-source.cpp index 0e898d8c83ab..68eafecf6795 100644 --- a/test/Index/Core/index-source.cpp +++ b/test/Index/Core/index-source.cpp @@ -21,7 +21,7 @@ public: }; TemplCls<int> gtv(0); -// CHECK: [[@LINE-1]]:1 | class(Gen)/C++ | TemplCls | c:@ST>1#T@TemplCls | <no-cgname> | Ref | rel: 0 +// CHECK: [[@LINE-1]]:1 | class(Gen)/C++ | TemplCls | c:@ST>1#T@TemplCls | <no-cgname> | Ref,RelCont | rel: 1 template <typename T> class BT { @@ -38,7 +38,7 @@ class BT { // CHECK: [[@LINE+1]]:23 | type-alias/C | size_t | typedef unsigned long size_t; // CHECK: [[@LINE+2]]:7 | function/C | operator new | c:@F@operator new#l# | __Znwm | -// CHECK: [[@LINE+1]]:20 | type-alias/C | size_t | {{.*}} | Ref | +// CHECK: [[@LINE+1]]:20 | type-alias/C | size_t | {{.*}} | Ref,RelCont | void* operator new(size_t sz); // CHECK: [[@LINE+1]]:37 | variable(Gen)/C++ | tmplVar | c:index-source.cpp@VT>1#T@tmplVar | __ZL7tmplVar | Def | rel: 0 @@ -46,8 +46,8 @@ template<typename T> static const T tmplVar = T(0); // CHECK: [[@LINE+1]]:29 | variable(Gen,TS)/C++ | tmplVar | c:index-source.cpp@tmplVar>#I | __ZL7tmplVarIiE | Def | rel: 0 template<> static const int tmplVar<int> = 0; // CHECK: [[@LINE+2]]:5 | variable/C | gvi | c:@gvi | _gvi | Def | rel: 0 -// CHECK: [[@LINE+1]]:11 | variable(Gen,TS)/C++ | tmplVar | c:index-source.cpp@tmplVar>#I | __ZL7tmplVarIiE | Ref,Read | rel: 0 +// CHECK: [[@LINE+1]]:11 | variable(Gen,TS)/C++ | tmplVar | c:index-source.cpp@tmplVar>#I | __ZL7tmplVarIiE | Ref,Read,RelCont | rel: 1 int gvi = tmplVar<int>; // CHECK: [[@LINE+2]]:5 | variable/C | gvf | c:@gvf | _gvf | Def | rel: 0 -// CHECK: [[@LINE+1]]:11 | variable(Gen)/C++ | tmplVar | c:index-source.cpp@VT>1#T@tmplVar | __ZL7tmplVar | Ref,Read | rel: 0 +// CHECK: [[@LINE+1]]:11 | variable(Gen)/C++ | tmplVar | c:index-source.cpp@VT>1#T@tmplVar | __ZL7tmplVar | Ref,Read,RelCont | rel: 1 int gvf = tmplVar<float>; diff --git a/test/Index/Core/index-source.m b/test/Index/Core/index-source.m index fc1b6232cfe8..3debcd262b24 100644 --- a/test/Index/Core/index-source.m +++ b/test/Index/Core/index-source.m @@ -5,18 +5,35 @@ -(void)meth; // CHECK: [[@LINE-1]]:1 | instance-method/ObjC | meth | c:objc(cs)Base(im)meth | -[Base meth] | Decl,Dyn,RelChild | rel: 1 // CHECK-NEXT: RelChild | Base | c:objc(cs)Base ++(Base*)class_meth; +// CHECK: [[@LINE-1]]:1 | class-method/ObjC | class_meth | c:objc(cs)Base(cm)class_meth | +[Base class_meth] | Decl,Dyn,RelChild | rel: 1 +// CHECK: [[@LINE-2]]:3 | class/ObjC | Base | c:objc(cs)Base | _OBJC_CLASS_$_Base | Ref,RelCont | rel: 1 +// CHECK-NEXT: RelCont | class_meth | c:objc(cs)Base(cm)class_meth + @end void foo(); -// CHECK: [[@LINE+1]]:6 | function/C | goo | c:@F@goo | _goo | Def | rel: 0 +// CHECK: [[@LINE+3]]:6 | function/C | goo | c:@F@goo | _goo | Def | rel: 0 +// CHECK: [[@LINE+2]]:10 | class/ObjC | Base | c:objc(cs)Base | _OBJC_CLASS_$_Base | Ref,RelCont | rel: 1 +// CHECK-NEXT: RelCont | goo | c:@F@goo void goo(Base *b) { - // CHECK: [[@LINE+2]]:3 | function/C | foo | c:@F@foo | _foo | Ref,Call,RelCall | rel: 1 - // CHECK-NEXT: RelCall | goo | c:@F@goo + // CHECK: [[@LINE+2]]:3 | function/C | foo | c:@F@foo | _foo | Ref,Call,RelCall,RelCont | rel: 1 + // CHECK-NEXT: RelCall,RelCont | goo | c:@F@goo foo(); - // CHECK: [[@LINE+3]]:6 | instance-method/ObjC | meth | c:objc(cs)Base(im)meth | -[Base meth] | Ref,Call,Dyn,RelRec,RelCall | rel: 2 - // CHECK-NEXT: RelCall | goo | c:@F@goo + // CHECK: [[@LINE+3]]:6 | instance-method/ObjC | meth | c:objc(cs)Base(im)meth | -[Base meth] | Ref,Call,Dyn,RelRec,RelCall,RelCont | rel: 2 + // CHECK-NEXT: RelCall,RelCont | goo | c:@F@goo // CHECK-NEXT: RelRec | Base | c:objc(cs)Base [b meth]; + + // CHECK: [[@LINE+2]]:4 | class/ObjC | Base | c:objc(cs)Base | _OBJC_CLASS_$_Base | Ref,RelCont | rel: 1 + // CHECK-NEXT: RelCont | goo | c:@F@goo + [Base class_meth]; + + // CHECK: [[@LINE+4]]:3 | class/ObjC | Base | c:objc(cs)Base | _OBJC_CLASS_$_Base | Ref,RelCont | rel: 1 + // CHECK-NEXT: RelCont | goo | c:@F@goo + // CHECK: [[@LINE+2]]:14 | class/ObjC | Base | c:objc(cs)Base | _OBJC_CLASS_$_Base | Ref,RelCont | rel: 1 + // CHECK-NEXT: RelCont | goo | c:@F@goo + Base *f = (Base *) 2; } // CHECK: [[@LINE+1]]:11 | protocol/ObjC | Prot1 | c:objc(pl)Prot1 | <no-cgname> | Decl | rel: 0 @@ -24,18 +41,18 @@ void goo(Base *b) { @end // CHECK: [[@LINE+3]]:11 | protocol/ObjC | Prot2 | c:objc(pl)Prot2 | <no-cgname> | Decl | rel: 0 -// CHECK: [[@LINE+2]]:17 | protocol/ObjC | Prot1 | c:objc(pl)Prot1 | <no-cgname> | Ref,RelBase | rel: 1 -// CHECK-NEXT: RelBase | Prot2 | c:objc(pl)Prot2 +// CHECK: [[@LINE+2]]:17 | protocol/ObjC | Prot1 | c:objc(pl)Prot1 | <no-cgname> | Ref,RelBase,RelCont | rel: 1 +// CHECK-NEXT: RelBase,RelCont | Prot2 | c:objc(pl)Prot2 @protocol Prot2<Prot1> @end // CHECK: [[@LINE+7]]:12 | class/ObjC | Sub | c:objc(cs)Sub | _OBJC_CLASS_$_Sub | Decl | rel: 0 -// CHECK: [[@LINE+6]]:18 | class/ObjC | Base | c:objc(cs)Base | _OBJC_CLASS_$_Base | Ref,RelBase | rel: 1 -// CHECK-NEXT: RelBase | Sub | c:objc(cs)Sub -// CHECK: [[@LINE+4]]:23 | protocol/ObjC | Prot2 | c:objc(pl)Prot2 | <no-cgname> | Ref,RelBase | rel: 1 -// CHECK-NEXT: RelBase | Sub | c:objc(cs)Sub -// CHECK: [[@LINE+2]]:30 | protocol/ObjC | Prot1 | c:objc(pl)Prot1 | <no-cgname> | Ref,RelBase | rel: 1 -// CHECK-NEXT: RelBase | Sub | c:objc(cs)Sub +// CHECK: [[@LINE+6]]:18 | class/ObjC | Base | c:objc(cs)Base | _OBJC_CLASS_$_Base | Ref,RelBase,RelCont | rel: 1 +// CHECK-NEXT: RelBase,RelCont | Sub | c:objc(cs)Sub +// CHECK: [[@LINE+4]]:23 | protocol/ObjC | Prot2 | c:objc(pl)Prot2 | <no-cgname> | Ref,RelBase,RelCont | rel: 1 +// CHECK-NEXT: RelBase,RelCont | Sub | c:objc(cs)Sub +// CHECK: [[@LINE+2]]:30 | protocol/ObjC | Prot1 | c:objc(pl)Prot1 | <no-cgname> | Ref,RelBase,RelCont | rel: 1 +// CHECK-NEXT: RelBase,RelCont | Sub | c:objc(cs)Sub @interface Sub : Base<Prot2, Prot1> @end @@ -68,8 +85,9 @@ enum { // CHECK: [[@LINE+1]]:13 | type-alias/C | jmp_buf | c:index-source.m@T@jmp_buf | <no-cgname> | Def | rel: 0 typedef int jmp_buf[(18)]; -// CHECK: [[@LINE+2]]:12 | function/C | setjmp | c:@F@setjmp | _setjmp | Decl | rel: 0 -// CHECK: [[@LINE+1]]:19 | type-alias/C | jmp_buf | c:index-source.m@T@jmp_buf | <no-cgname> | Ref | rel: 0 +// CHECK: [[@LINE+3]]:12 | function/C | setjmp | c:@F@setjmp | _setjmp | Decl | rel: 0 +// CHECK: [[@LINE+2]]:19 | type-alias/C | jmp_buf | c:index-source.m@T@jmp_buf | <no-cgname> | Ref,RelCont | rel: 1 +// CHECK-NEXT: RelCont | setjmp | c:@F@setjmp extern int setjmp(jmp_buf); @class I1; @@ -80,26 +98,40 @@ extern int setjmp(jmp_buf); @interface I2 @property (readwrite) id prop; + +// CHECK: [[@LINE+4]]:63 | instance-property(IB,IBColl)/ObjC | buttons | c:objc(cs)I2(py)buttons | <no-cgname> | Decl,RelChild | rel: 1 +// CHECK-NEXT: RelChild | I2 | c:objc(cs)I2 +// CHECK: [[@LINE+2]]:50 | class/ObjC | I1 | c:objc(cs)I1 | _OBJC_CLASS_$_I1 | Ref,RelCont,RelIBType | rel: 1 +// CHECK-NEXT: RelCont,RelIBType | buttons | c:objc(cs)I2(py)buttons +@property (nonatomic, strong) IBOutletCollection(I1) NSArray *buttons; @end // CHECK: [[@LINE+2]]:17 | field/ObjC | _prop | c:objc(cs)I2@_prop | <no-cgname> | Def,Impl,RelChild | rel: 1 // CHECK-NEXT: RelChild | I2 | c:objc(cs)I2 @implementation I2 -// CHECK: [[@LINE+5]]:13 | instance-property/ObjC | prop | c:objc(cs)I2(py)prop | <no-cgname> | Ref | rel: 0 -// CHECK: [[@LINE+4]]:13 | instance-method/ObjC | prop | c:objc(cs)I2(im)prop | -[I2 prop] | Def,RelChild | rel: 1 +// CHECK: [[@LINE+6]]:13 | instance-property/ObjC | prop | c:objc(cs)I2(py)prop | <no-cgname> | Ref,RelCont | rel: 1 +// CHECK-NEXT: RelCont | I2 | c:objc(cs)I2 +// CHECK: [[@LINE+4]]:13 | instance-method/acc-get/ObjC | prop | c:objc(cs)I2(im)prop | -[I2 prop] | Def,RelChild | rel: 1 // CHECK-NEXT: RelChild | I2 | c:objc(cs)I2 -// CHECK: [[@LINE+2]]:13 | instance-method/ObjC | setProp: | c:objc(cs)I2(im)setProp: | -[I2 setProp:] | Def,RelChild | rel: 1 +// CHECK: [[@LINE+2]]:13 | instance-method/acc-set/ObjC | setProp: | c:objc(cs)I2(im)setProp: | -[I2 setProp:] | Def,RelChild | rel: 1 // CHECK-NEXT: RelChild | I2 | c:objc(cs)I2 @synthesize prop = _prop; + +// CHECK: [[@LINE+5]]:1 | instance-method(IB)/ObjC | doAction:foo: | c:objc(cs)I2(im)doAction:foo: | -[I2 doAction:foo:] | Def,Dyn,RelChild | rel: 1 +// CHECK-NEXT: RelChild | I2 | c:objc(cs)I2 +// CHECK: [[@LINE+3]]:22 | class/ObjC | I1 | c:objc(cs)I1 | _OBJC_CLASS_$_I1 | Ref,RelCont,RelIBType | rel: 1 +// CHECK-NEXT: RelCont,RelIBType | doAction:foo: | c:objc(cs)I2(im)doAction:foo: +// CHECK: [[@LINE+1]]:39 | class/ObjC | I1 | c:objc(cs)I1 | _OBJC_CLASS_$_I1 | Ref,RelCont | rel: 1 +-(IBAction)doAction:(I1 *)sender foo:(I1 *)bar {} @end @interface I3 @property (readwrite) id prop; -// CHECK: [[@LINE+3]]:1 | instance-method/ObjC | prop | c:objc(cs)I3(im)prop | -[I3 prop] | Decl,Dyn,RelChild,RelAcc | rel: 2 +// CHECK: [[@LINE+3]]:1 | instance-method/acc-get/ObjC | prop | c:objc(cs)I3(im)prop | -[I3 prop] | Decl,Dyn,RelChild,RelAcc | rel: 2 // CHECK-NEXT: RelChild | I3 | c:objc(cs)I3 // CHECK-NEXT: RelAcc | prop | c:objc(cs)I3(py)prop -(id)prop; -// CHECK: [[@LINE+3]]:1 | instance-method/ObjC | setProp: | c:objc(cs)I3(im)setProp: | -[I3 setProp:] | Decl,Dyn,RelChild,RelAcc | rel: 2 +// CHECK: [[@LINE+3]]:1 | instance-method/acc-set/ObjC | setProp: | c:objc(cs)I3(im)setProp: | -[I3 setProp:] | Decl,Dyn,RelChild,RelAcc | rel: 2 // CHECK-NEXT: RelChild | I3 | c:objc(cs)I3 // CHECK-NEXT: RelAcc | prop | c:objc(cs)I3(py)prop -(void)setProp:(id)p; @@ -107,26 +139,27 @@ extern int setjmp(jmp_buf); // CHECK: [[@LINE+1]]:17 | class/ObjC | I3 | c:objc(cs)I3 | <no-cgname> | Def | rel: 0 @implementation I3 -// CHECK: [[@LINE+3]]:13 | instance-property/ObjC | prop | c:objc(cs)I3(py)prop | <no-cgname> | Ref | rel: 0 -// CHECK: [[@LINE+2]]:13 | instance-method/ObjC | prop | c:objc(cs)I3(im)prop | -[I3 prop] | Def,RelChild | rel: 1 -// CHECK: [[@LINE+1]]:13 | instance-method/ObjC | setProp: | c:objc(cs)I3(im)setProp: | -[I3 setProp:] | Def,RelChild | rel: 1 +// CHECK: [[@LINE+4]]:13 | instance-property/ObjC | prop | c:objc(cs)I3(py)prop | <no-cgname> | Ref,RelCont | rel: 1 +// CHECK-NEXT: RelCont | I3 | c:objc(cs)I3 +// CHECK: [[@LINE+2]]:13 | instance-method/acc-get/ObjC | prop | c:objc(cs)I3(im)prop | -[I3 prop] | Def,RelChild | rel: 1 +// CHECK: [[@LINE+1]]:13 | instance-method/acc-set/ObjC | setProp: | c:objc(cs)I3(im)setProp: | -[I3 setProp:] | Def,RelChild | rel: 1 @synthesize prop = _prop; @end -// CHECK: [[@LINE+5]]:12 | class/ObjC | I3 | c:objc(cs)I3 | _OBJC_CLASS_$_I3 | Ref,RelExt | rel: 1 -// CHECK-NEXT: RelExt | bar | c:objc(cy)I3@bar +// CHECK: [[@LINE+5]]:12 | class/ObjC | I3 | c:objc(cs)I3 | _OBJC_CLASS_$_I3 | Ref,RelExt,RelCont | rel: 1 +// CHECK-NEXT: RelExt,RelCont | bar | c:objc(cy)I3@bar // CHECK: [[@LINE+3]]:15 | extension/ObjC | bar | c:objc(cy)I3@bar | <no-cgname> | Decl | rel: 0 -// CHECK: [[@LINE+2]]:21 | protocol/ObjC | Prot1 | c:objc(pl)Prot1 | <no-cgname> | Ref,RelBase | rel: 1 -// CHECK-NEXT: RelBase | bar | c:objc(cy)I3@bar +// CHECK: [[@LINE+2]]:21 | protocol/ObjC | Prot1 | c:objc(pl)Prot1 | <no-cgname> | Ref,RelBase,RelCont | rel: 1 +// CHECK-NEXT: RelBase,RelCont | bar | c:objc(cy)I3@bar @interface I3(bar) <Prot1> @end -// CHECK: [[@LINE+2]]:17 | class/ObjC | I3 | c:objc(cs)I3 | _OBJC_CLASS_$_I3 | Ref | rel: 0 +// CHECK: [[@LINE+2]]:17 | class/ObjC | I3 | c:objc(cs)I3 | _OBJC_CLASS_$_I3 | Ref,RelCont | rel: 1 // CHECK: [[@LINE+1]]:20 | extension/ObjC | I3 | c:objc(cy)I3@bar | <no-cgname> | Def | rel: 0 @implementation I3(bar) @end -// CHECK: [[@LINE+1]]:12 | extension/ObjC | <no-name> | <no-usr> | <no-cgname> | Decl | rel: 0 +// CHECK-NOT: [[@LINE+1]]:12 | extension/ObjC | @interface NonExistent() @end @@ -137,15 +170,15 @@ extern int setjmp(jmp_buf); @end // CHECK: [[@LINE+4]]:41 | type-alias/C | MyEnumerator | c:index-source.m@T@MyEnumerator | <no-cgname> | Def | rel: 0 -// CHECK: [[@LINE+3]]:26 | protocol/ObjC | MyEnumerating | c:objc(pl)MyEnumerating | <no-cgname> | Ref | rel: 0 -// CHECK: [[@LINE+2]]:9 | class/ObjC | MyGenCls | c:objc(cs)MyGenCls | _OBJC_CLASS_$_MyGenCls | Ref | rel: 0 -// CHECK: [[@LINE+1]]:18 | class/ObjC | Base | c:objc(cs)Base | _OBJC_CLASS_$_Base | Ref | rel: 0 +// CHECK: [[@LINE+3]]:26 | protocol/ObjC | MyEnumerating | c:objc(pl)MyEnumerating | <no-cgname> | Ref,RelCont | rel: 1 +// CHECK: [[@LINE+2]]:9 | class/ObjC | MyGenCls | c:objc(cs)MyGenCls | _OBJC_CLASS_$_MyGenCls | Ref,RelCont | rel: 1 +// CHECK: [[@LINE+1]]:18 | class/ObjC | Base | c:objc(cs)Base | _OBJC_CLASS_$_Base | Ref,RelCont | rel: 1 typedef MyGenCls<Base *><MyEnumerating> MyEnumerator; // CHECK: [[@LINE+5]]:12 | class/ObjC | PermanentEnumerator | c:objc(cs)PermanentEnumerator | _OBJC_CLASS_$_PermanentEnumerator | Decl | rel: 0 -// CHECK: [[@LINE+4]]:34 | class/ObjC | MyGenCls | c:objc(cs)MyGenCls | _OBJC_CLASS_$_MyGenCls | Ref,RelBase | rel: 1 -// CHECK-NEXT: RelBase | PermanentEnumerator | c:objc(cs)PermanentEnumerator -// CHECK: [[@LINE+2]]:34 | protocol/ObjC | MyEnumerating | c:objc(pl)MyEnumerating | <no-cgname> | Ref,RelBase | rel: 1 -// CHECK-NEXT: RelBase | PermanentEnumerator | c:objc(cs)PermanentEnumerator +// CHECK: [[@LINE+4]]:34 | class/ObjC | MyGenCls | c:objc(cs)MyGenCls | _OBJC_CLASS_$_MyGenCls | Ref,RelBase,RelCont | rel: 1 +// CHECK-NEXT: RelBase,RelCont | PermanentEnumerator | c:objc(cs)PermanentEnumerator +// CHECK: [[@LINE+2]]:34 | protocol/ObjC | MyEnumerating | c:objc(pl)MyEnumerating | <no-cgname> | Ref,RelBase,RelCont | rel: 1 +// CHECK-NEXT: RelBase,RelCont | PermanentEnumerator | c:objc(cs)PermanentEnumerator @interface PermanentEnumerator : MyEnumerator @end diff --git a/test/Index/Core/index-subkinds.m b/test/Index/Core/index-subkinds.m index 38be73b31e91..6783f6dde308 100644 --- a/test/Index/Core/index-subkinds.m +++ b/test/Index/Core/index-subkinds.m @@ -26,12 +26,12 @@ -(void)testIt2 {} @end -// CHECK: [[@LINE+3]]:12 | class(test)/ObjC | MyTestCase | c:objc(cs)MyTestCase | _OBJC_CLASS_$_MyTestCase | Ref,RelExt | rel: 1 -// CHECK-NEXT: RelExt | cat | c:objc(cy)MyTestCase@cat +// CHECK: [[@LINE+3]]:12 | class(test)/ObjC | MyTestCase | c:objc(cs)MyTestCase | _OBJC_CLASS_$_MyTestCase | Ref,RelExt,RelCont | rel: 1 +// CHECK-NEXT: RelExt,RelCont | cat | c:objc(cy)MyTestCase@cat // CHECK: [[@LINE+1]]:23 | extension/ObjC | cat | c:objc(cy)MyTestCase@cat | <no-cgname> | Decl | rel: 0 @interface MyTestCase(cat) @end -// CHECK: [[@LINE+2]]:17 | class(test)/ObjC | MyTestCase | c:objc(cs)MyTestCase | _OBJC_CLASS_$_MyTestCase | Ref | rel: 0 +// CHECK: [[@LINE+2]]:17 | class(test)/ObjC | MyTestCase | c:objc(cs)MyTestCase | _OBJC_CLASS_$_MyTestCase | Ref,RelCont | rel: 1 // CHECK: [[@LINE+1]]:28 | extension/ObjC | MyTestCase | c:objc(cy)MyTestCase@cat | <no-cgname> | Def | rel: 0 @implementation MyTestCase(cat) // CHECK: [[@LINE+1]]:1 | instance-method(test)/ObjC | testInCat | c:objc(cs)MyTestCase(im)testInCat | -[MyTestCase(cat) testInCat] | Def,Dyn,RelChild | rel: 1 @@ -42,7 +42,7 @@ @class NSButton; @interface IBCls -// CHECK: [[@LINE+2]]:34 | instance-method/ObjC | prop | c:objc(cs)IBCls(im)prop | -[IBCls prop] | Decl,Dyn,RelChild,RelAcc | rel: 2 +// CHECK: [[@LINE+2]]:34 | instance-method/acc-get/ObjC | prop | c:objc(cs)IBCls(im)prop | -[IBCls prop] | Decl,Dyn,RelChild,RelAcc | rel: 2 // CHECK: [[@LINE+1]]:34 | instance-property(IB)/ObjC | prop | c:objc(cs)IBCls(py)prop | <no-cgname> | Decl,RelChild | rel: 1 @property (readonly) IBOutlet id prop; // CHECK: [[@LINE+1]]:54 | instance-property(IB,IBColl)/ObjC | propColl | c:objc(cs)IBCls(py)propColl | <no-cgname> | Decl,RelChild | rel: 1 diff --git a/test/Index/Core/index-with-module.m b/test/Index/Core/index-with-module.m index 03fd5cd5b8d3..e50b247e8d57 100644 --- a/test/Index/Core/index-with-module.m +++ b/test/Index/Core/index-with-module.m @@ -7,6 +7,6 @@ #include "ModA.h" void foo() { - // CHECK: [[@LINE+1]]:3 | function/C | ModA_func | c:@F@ModA_func | {{.*}} | Ref,Call,RelCall | rel: 1 + // CHECK: [[@LINE+1]]:3 | function/C | ModA_func | c:@F@ModA_func | {{.*}} | Ref,Call,RelCall,RelCont | rel: 1 ModA_func(); } diff --git a/test/Index/index-templates.cpp b/test/Index/index-templates.cpp index 79b9c181ecaf..966cc4f5ea7f 100644 --- a/test/Index/index-templates.cpp +++ b/test/Index/index-templates.cpp @@ -49,9 +49,9 @@ template class vector<int*>; struct Z4 { template<typename T> T getAs(); }; - +template<typename T, T> struct value { }; void template_exprs() { - f<Unsigned, OneDimension, array>(array<Unsigned, OneDimension>()); + f<Unsigned, OneDimension, value>(value<Unsigned, OneDimension>()); Z4().getAs<Unsigned>(); } @@ -173,7 +173,7 @@ using alias = T; // CHECK-LOAD: index-templates.cpp:54:3: DeclRefExpr=f:4:6 RefName=[54:3 - 54:4] RefName=[54:4 - 54:35] Extent=[54:3 - 54:35] // CHECK-LOAD: index-templates.cpp:54:5: TypeRef=Unsigned:42:18 Extent=[54:5 - 54:13] // CHECK-LOAD: index-templates.cpp:54:15: DeclRefExpr=OneDimension:35:16 Extent=[54:15 - 54:27] -// CHECK-LOAD: index-templates.cpp:54:29: TemplateRef=array:37:8 Extent=[54:29 - 54:34] +// CHECK-LOAD: index-templates.cpp:54:29: TemplateRef=value:52:32 Extent=[54:29 - 54:34] // CHECK-LOAD: index-templates.cpp:55:8: MemberRefExpr=getAs:50:26 SingleRefName=[55:8 - 55:13] RefName=[55:8 - 55:13] Extent=[55:3 - 55:23] // CHECK-LOAD: index-templates.cpp:55:3: CallExpr=Z4:49:8 Extent=[55:3 - 55:7] // CHECK-LOAD: index-templates.cpp:55:14: TypeRef=Unsigned:42:18 Extent=[55:14 - 55:22] diff --git a/test/Misc/ast-dump-decl.cpp b/test/Misc/ast-dump-decl.cpp index 1cfcd509efab..c966e133eb5d 100644 --- a/test/Misc/ast-dump-decl.cpp +++ b/test/Misc/ast-dump-decl.cpp @@ -336,7 +336,6 @@ namespace testCanonicalTemplate { // CHECK-NEXT: ClassTemplateDecl{{.*}} TestClassTemplate // CHECK-NEXT: TemplateTypeParmDecl // CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate - // CHECK-NEXT: ClassTemplateSpecialization{{.*}} 'TestClassTemplate' // CHECK-NEXT: ClassTemplateSpecializationDecl{{.*}} class TestClassTemplate // CHECK-NEXT: TemplateArgument{{.*}}A // CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate diff --git a/test/Modules/Inputs/FooFramework.framework/Modules/module.modulemap b/test/Modules/Inputs/FooFramework.framework/Modules/module.modulemap new file mode 100644 index 000000000000..62e56364abaf --- /dev/null +++ b/test/Modules/Inputs/FooFramework.framework/Modules/module.modulemap @@ -0,0 +1,12 @@ +framework module FooFramework { + umbrella header "FooUmbrella.h" + + export * + module * { + export * + } + + explicit module Private { + textual header "Baz_Private.h" + } +} diff --git a/test/Modules/Inputs/FooFramework.framework/PrivateHeaders/Bar.h b/test/Modules/Inputs/FooFramework.framework/PrivateHeaders/Bar.h new file mode 100644 index 000000000000..d16b395055f9 --- /dev/null +++ b/test/Modules/Inputs/FooFramework.framework/PrivateHeaders/Bar.h @@ -0,0 +1,2 @@ +@interface Bar +@end diff --git a/test/Modules/Inputs/FooFramework.framework/PrivateHeaders/Baz_Private.h b/test/Modules/Inputs/FooFramework.framework/PrivateHeaders/Baz_Private.h new file mode 100644 index 000000000000..3ea082b874c0 --- /dev/null +++ b/test/Modules/Inputs/FooFramework.framework/PrivateHeaders/Baz_Private.h @@ -0,0 +1,3 @@ +#ifndef Baz_h +#define Baz_h +#endif /* Baz_h */ diff --git a/test/Modules/Inputs/FooFramework.framework/PrivateHeaders/Foo.h b/test/Modules/Inputs/FooFramework.framework/PrivateHeaders/Foo.h new file mode 100644 index 000000000000..26b96988d588 --- /dev/null +++ b/test/Modules/Inputs/FooFramework.framework/PrivateHeaders/Foo.h @@ -0,0 +1,10 @@ +__attribute__((objc_root_class)) +@interface NSObject ++ (instancetype) alloc; +- (instancetype) init; +- (instancetype)retain; +- (void)release; +@end + +@interface Foo : NSObject +@end diff --git a/test/Modules/Inputs/FooFramework.framework/PrivateHeaders/FooUmbrella.h b/test/Modules/Inputs/FooFramework.framework/PrivateHeaders/FooUmbrella.h new file mode 100644 index 000000000000..c752fb299e00 --- /dev/null +++ b/test/Modules/Inputs/FooFramework.framework/PrivateHeaders/FooUmbrella.h @@ -0,0 +1,3 @@ +#import <FooFramework/Foo.h> +#import <FooFramework/Bar.h> + diff --git a/test/Modules/Inputs/PR31469/empty.h b/test/Modules/Inputs/PR31469/empty.h new file mode 100644 index 000000000000..51e115f57fc6 --- /dev/null +++ b/test/Modules/Inputs/PR31469/empty.h @@ -0,0 +1 @@ +// This file is triggers loading of module M. diff --git a/test/Modules/Inputs/PR31469/module.modulemap b/test/Modules/Inputs/PR31469/module.modulemap new file mode 100644 index 000000000000..bada81d04ee3 --- /dev/null +++ b/test/Modules/Inputs/PR31469/module.modulemap @@ -0,0 +1,5 @@ +module M { + module "textual_shadow" { header "textual_file_shadow.h" export *} + module "trigger" { header "empty.h" export * } + export * +} diff --git a/test/Modules/Inputs/PR31469/textual.h b/test/Modules/Inputs/PR31469/textual.h new file mode 100644 index 000000000000..abdc662fb5ef --- /dev/null +++ b/test/Modules/Inputs/PR31469/textual.h @@ -0,0 +1,17 @@ +namespace A { +inline +namespace __1 { + template <class _Tp> class allocator; + template <class _Tp, class _Alloc = allocator<_Tp>> class list; + template <class _VoidPtr> class __list_iterator { + //template <class> friend class list; // causes another crash in ASTDeclReader::attachPreviousDecl + template <class, class> friend class list; + }; + template <class _Tp, class _Alloc> class __list_imp {}; + template <class _Tp, class _Alloc> class list : __list_imp<_Tp, _Alloc> { + public: + list() {} + }; + template <class _Tp> void f(list<_Tp>); +} +} diff --git a/test/Modules/Inputs/PR31469/textual_file_shadow.h b/test/Modules/Inputs/PR31469/textual_file_shadow.h new file mode 100644 index 000000000000..48a53dd4a83f --- /dev/null +++ b/test/Modules/Inputs/PR31469/textual_file_shadow.h @@ -0,0 +1,2 @@ +#include "textual.h" + diff --git a/test/Modules/Inputs/import-textual/M/A/A.h b/test/Modules/Inputs/import-textual/M/A/A.h new file mode 100644 index 000000000000..ebe4979d7c1e --- /dev/null +++ b/test/Modules/Inputs/import-textual/M/A/A.h @@ -0,0 +1,4 @@ + +#import "someheader.h" + +typedef myint aint; diff --git a/test/Modules/Inputs/import-textual/M/B/B.h b/test/Modules/Inputs/import-textual/M/B/B.h new file mode 100644 index 000000000000..ba85071c014a --- /dev/null +++ b/test/Modules/Inputs/import-textual/M/B/B.h @@ -0,0 +1,4 @@ + +#import "someheader.h" + +typedef myint bint; diff --git a/test/Modules/Inputs/import-textual/M/module.modulemap b/test/Modules/Inputs/import-textual/M/module.modulemap new file mode 100644 index 000000000000..f80194876caa --- /dev/null +++ b/test/Modules/Inputs/import-textual/M/module.modulemap @@ -0,0 +1,17 @@ + +module M { + + module A { + header "A/A.h" + textual header "someheader.h" + export * + } + + module B { + header "B/B.h" + textual header "someheader.h" + export * + } + + export * +} diff --git a/test/Modules/Inputs/import-textual/M/someheader.h b/test/Modules/Inputs/import-textual/M/someheader.h new file mode 100644 index 000000000000..16fae408724d --- /dev/null +++ b/test/Modules/Inputs/import-textual/M/someheader.h @@ -0,0 +1,6 @@ +#ifndef C_GUARD +#define C_GUARD + +typedef int myint; + +#endif diff --git a/test/Modules/Inputs/import-textual/M2/A/A.h b/test/Modules/Inputs/import-textual/M2/A/A.h new file mode 100644 index 000000000000..ebe4979d7c1e --- /dev/null +++ b/test/Modules/Inputs/import-textual/M2/A/A.h @@ -0,0 +1,4 @@ + +#import "someheader.h" + +typedef myint aint; diff --git a/test/Modules/Inputs/import-textual/M2/B/B.h b/test/Modules/Inputs/import-textual/M2/B/B.h new file mode 100644 index 000000000000..ba85071c014a --- /dev/null +++ b/test/Modules/Inputs/import-textual/M2/B/B.h @@ -0,0 +1,4 @@ + +#import "someheader.h" + +typedef myint bint; diff --git a/test/Modules/Inputs/import-textual/M2/module.modulemap b/test/Modules/Inputs/import-textual/M2/module.modulemap new file mode 100644 index 000000000000..f80194876caa --- /dev/null +++ b/test/Modules/Inputs/import-textual/M2/module.modulemap @@ -0,0 +1,17 @@ + +module M { + + module A { + header "A/A.h" + textual header "someheader.h" + export * + } + + module B { + header "B/B.h" + textual header "someheader.h" + export * + } + + export * +} diff --git a/test/Modules/Inputs/import-textual/M2/someheader.h b/test/Modules/Inputs/import-textual/M2/someheader.h new file mode 100644 index 000000000000..df2009a019b5 --- /dev/null +++ b/test/Modules/Inputs/import-textual/M2/someheader.h @@ -0,0 +1 @@ +typedef int myint; diff --git a/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/cstddef b/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/cstddef new file mode 100644 index 000000000000..4898c05fdbb5 --- /dev/null +++ b/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/cstddef @@ -0,0 +1,9 @@ +#ifndef _LIBCPP_CSTDDEF +#define _LIBCPP_CSTDDEF + +#include <stddef.h> +#include <type_traits> + +typedef ptrdiff_t my_ptrdiff_t; + +#endif diff --git a/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/math.h b/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/math.h index f761b910f3ef..9e2b69361259 100644 --- a/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/math.h +++ b/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/math.h @@ -4,4 +4,6 @@ #include_next <math.h> template<typename T> T abs(T t) { return (t < 0) ? -t : t; } +#include <type_traits> + #endif diff --git a/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/module.modulemap b/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/module.modulemap index b06142a61a20..f57c11c42385 100644 --- a/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/module.modulemap +++ b/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/module.modulemap @@ -6,5 +6,7 @@ module "libc++" { // FIXME: remove "textual" from stdint module below once the issue // between umbrella headers and builtins is resolved. module stdint { textual header "stdint.h" export * } + module type_traits { header "type_traits" export * } + module cstddef { header "cstddef" export * } module __config { header "__config" export * } } diff --git a/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/stddef.h b/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/stddef.h index bd42008e1695..14167cfe1d72 100644 --- a/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/stddef.h +++ b/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/stddef.h @@ -2,5 +2,6 @@ #define LIBCXX_STDDEF_H #include <__config> +#include_next <stddef.h> #endif diff --git a/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/type_traits b/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/type_traits new file mode 100644 index 000000000000..a91056e008a0 --- /dev/null +++ b/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/type_traits @@ -0,0 +1,6 @@ +#ifndef _LIBCPP_TYPE_TRAITS +#define _LIBCPP_TYPE_TRAITS + +#include <cstddef> + +#endif diff --git a/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/module.modulemap b/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/module.modulemap index 7244cb0987e7..25b9468d2916 100644 --- a/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/module.modulemap +++ b/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/module.modulemap @@ -5,4 +5,12 @@ module libc [no_undeclared_includes] { module stdint { header "stdint.h" export * } module stdio { header "stdio.h" export * } module util { header "util.h" export * } + module POSIX { + module sys { + module types { + umbrella header "sys/_types/_types.h" + export * + } + } + } } diff --git a/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/stddef.h b/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/stddef.h index eca72412a651..b98249f0864f 100644 --- a/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/stddef.h +++ b/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/stddef.h @@ -1 +1,6 @@ -// stddef.h +#ifndef __STDDEF_H__ +#define __STDDEF_H__ + +#include "sys/_types/_ptrdiff_t.h" + +#endif diff --git a/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/sys/_types/_ptrdiff_t.h b/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/sys/_types/_ptrdiff_t.h new file mode 100644 index 000000000000..d14110e4644c --- /dev/null +++ b/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/sys/_types/_ptrdiff_t.h @@ -0,0 +1,4 @@ +#ifndef _PTRDIFF_T +#define _PTRDIFF_T +typedef int * ptrdiff_t; +#endif /* _PTRDIFF_T */ diff --git a/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/sys/_types/_types.h b/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/sys/_types/_types.h new file mode 100644 index 000000000000..33d5e514433c --- /dev/null +++ b/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/sys/_types/_types.h @@ -0,0 +1,6 @@ +#ifndef _SYS_TYPES_UMBRELLA +#define _SYS_TYPES_UMBRELLA + +#include "_ptrdiff_t.h" + +#endif diff --git a/test/Modules/Inputs/module-impl-with-link/foo.h b/test/Modules/Inputs/module-impl-with-link/foo.h new file mode 100644 index 000000000000..90fe1bcc5851 --- /dev/null +++ b/test/Modules/Inputs/module-impl-with-link/foo.h @@ -0,0 +1 @@ +//empty diff --git a/test/Modules/Inputs/module-impl-with-link/module.modulemap b/test/Modules/Inputs/module-impl-with-link/module.modulemap new file mode 100644 index 000000000000..b85f8b6fe804 --- /dev/null +++ b/test/Modules/Inputs/module-impl-with-link/module.modulemap @@ -0,0 +1,4 @@ +module Clib { + header "foo.h" + link "Clib" +} diff --git a/test/Modules/builtin-import.mm b/test/Modules/builtin-import.mm new file mode 100644 index 000000000000..2536ac51c42f --- /dev/null +++ b/test/Modules/builtin-import.mm @@ -0,0 +1,12 @@ +// REQUIRES: system-darwin + +// RUN: rm -rf %t +// RUN: %clang -cc1 -fsyntax-only -nostdinc++ -isysroot %S/Inputs/libc-libcxx/sysroot -isystem %S/Inputs/libc-libcxx/sysroot/usr/include/c++/v1 -std=c++11 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -x objective-c++ -fmodules-local-submodule-visibility %s + +#include <stdio.h> +#include <stddef.h> +#include <cstddef> + +typedef ptrdiff_t try1_ptrdiff_t; +typedef my_ptrdiff_t try2_ptrdiff_t; + diff --git a/test/Modules/cxx-templates.cpp b/test/Modules/cxx-templates.cpp index 401b7704900b..59e9136bd142 100644 --- a/test/Modules/cxx-templates.cpp +++ b/test/Modules/cxx-templates.cpp @@ -49,14 +49,8 @@ void g() { // expected-note@Inputs/cxx-templates-a.h:11 {{candidate}} // expected-note@Inputs/cxx-templates-b.h:11 {{candidate}} - // FIXME: This should be valid, but we incorrectly match the template template - // argument against both template template parameters. - template_param_kinds_3<Tmpl_T_T_A>(); // expected-error {{ambiguous}} - // expected-note@Inputs/cxx-templates-a.h:12 {{candidate}} - // expected-note@Inputs/cxx-templates-b.h:12 {{candidate}} - template_param_kinds_3<Tmpl_T_T_B>(); // expected-error {{ambiguous}} - // expected-note@Inputs/cxx-templates-a.h:12 {{candidate}} - // expected-note@Inputs/cxx-templates-b.h:12 {{candidate}} + template_param_kinds_3<Tmpl_T_T_A>(); + template_param_kinds_3<Tmpl_T_T_B>(); // Trigger the instantiation of a template in 'a' that uses a type defined in // 'common'. That type is not visible here. diff --git a/test/Modules/import-textual-noguard.mm b/test/Modules/import-textual-noguard.mm new file mode 100644 index 000000000000..dd124b6609d0 --- /dev/null +++ b/test/Modules/import-textual-noguard.mm @@ -0,0 +1,8 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -fmodules -fimplicit-module-maps -I%S/Inputs/import-textual/M2 -fmodules-cache-path=%t -x objective-c++ -fmodules-local-submodule-visibility %s -verify + +#include "A/A.h" // expected-error {{could not build module 'M'}} +#include "B/B.h" + +typedef aint xxx; +typedef bint yyy; diff --git a/test/Modules/import-textual.mm b/test/Modules/import-textual.mm new file mode 100644 index 000000000000..6593239d7fd7 --- /dev/null +++ b/test/Modules/import-textual.mm @@ -0,0 +1,10 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -fmodules -fimplicit-module-maps -I%S/Inputs/import-textual/M -fmodules-cache-path=%t -x objective-c++ -fmodules-local-submodule-visibility %s -verify + +// expected-no-diagnostics + +#include "A/A.h" +#include "B/B.h" + +typedef aint xxx; +typedef bint yyy; diff --git a/test/Modules/module-impl-with-link.c b/test/Modules/module-impl-with-link.c new file mode 100644 index 000000000000..5e5ca83aafd6 --- /dev/null +++ b/test/Modules/module-impl-with-link.c @@ -0,0 +1,7 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -fmodule-name=Clib %s -I %S/Inputs/module-impl-with-link -emit-llvm -o - +#include "foo.h" +// CHECK: !{{[0-9]+}} = !{i32 6, !"Linker Options", ![[LINK_OPTIONS:[0-9]+]]} +// Make sure we don't generate linker option for module Clib since this TU is +// an implementation of Clib. +// CHECK: ![[LINK_OPTIONS]] = !{} diff --git a/test/Modules/pr31469.cpp b/test/Modules/pr31469.cpp new file mode 100644 index 000000000000..8f7d52285c87 --- /dev/null +++ b/test/Modules/pr31469.cpp @@ -0,0 +1,15 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -std=c++11 -I%S/Inputs/PR31469 -verify %s +// RUN: %clang_cc1 -std=c++11 -I%S/Inputs/PR31469 -fmodules -fmodules-local-submodule-visibility \ +// RUN: -fimplicit-module-maps -fmodules-cache-path=%t -verify %s + +#include "textual.h" +#include "empty.h" + +namespace A { + template <class _Tp> void f(); +} + +A::list<int> use; + +// expected-no-diagnostics diff --git a/test/Modules/textual-hdr-in-umbrella-hdr.m b/test/Modules/textual-hdr-in-umbrella-hdr.m new file mode 100644 index 000000000000..f92cdb91b236 --- /dev/null +++ b/test/Modules/textual-hdr-in-umbrella-hdr.m @@ -0,0 +1,10 @@ +// RUN: rm -rf %t.cache +// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t.cache \ +// RUN: %s -fsyntax-only -F %S/Inputs -Wincomplete-umbrella -verify + +// expected-no-diagnostics + +#import <FooFramework/Foo.h> + +@implementation Foo +@end diff --git a/test/OpenMP/nesting_of_regions.cpp b/test/OpenMP/nesting_of_regions.cpp index 9b3a2b39be52..6282de4cc478 100644 --- a/test/OpenMP/nesting_of_regions.cpp +++ b/test/OpenMP/nesting_of_regions.cpp @@ -208,6 +208,12 @@ void foo() { for (int i = 0; i < 10; ++i) ; } +#pragma omp parallel + { +#pragma omp target teams distribute simd // OK + for (int i = 0; i < 10; ++i) + ; + } // SIMD DIRECTIVE #pragma omp simd @@ -453,6 +459,12 @@ void foo() { for (int j = 0; j < 10; ++j) ; } +#pragma omp simd + for (int i = 0; i < 10; ++i) { +#pragma omp target teams distribute simd // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int j = 0; j < 10; ++j) + ; + } // FOR DIRECTIVE #pragma omp for @@ -711,6 +723,12 @@ void foo() { for (int j = 0; j < 10; ++j) ; } +#pragma omp for + for (int i = 0; i < 10; ++i) { +#pragma omp target teams distribute simd // OK + for (int j = 0; j < 10; ++j) + ; + } // FOR SIMD DIRECTIVE #pragma omp for simd @@ -957,6 +975,12 @@ void foo() { for (int j = 0; j < 10; ++j) ; } +#pragma omp for simd + for (int i = 0; i < 10; ++i) { +#pragma omp target teams distribute simd // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int j = 0; j < 10; ++j) + ; + } // SECTIONS DIRECTIVE #pragma omp sections @@ -1220,6 +1244,12 @@ void foo() { for (int i = 0; i < 10; ++i) ; } +#pragma omp sections + { +#pragma omp target teams distribute simd // OK + for (int i = 0; i < 10; ++i) + ; + } // SECTION DIRECTIVE #pragma omp section // expected-error {{orphaned 'omp section' directives are prohibited, it must be closely nested to a sections region}} @@ -1549,6 +1579,13 @@ void foo() { for (int i = 0; i < 10; ++i) ; } +#pragma omp sections + { +#pragma omp section +#pragma omp target teams distribute simd // OK + for (int i = 0; i < 10; ++i) + ; + } // SINGLE DIRECTIVE #pragma omp single @@ -1798,6 +1835,12 @@ void foo() { for (int i = 0; i < 10; ++i) ; } +#pragma omp single + { +#pragma omp target teams distribute simd // OK + for (int i = 0; i < 10; ++i) + ; + } // MASTER DIRECTIVE #pragma omp master @@ -2047,6 +2090,12 @@ void foo() { for (int i = 0; i < 10; ++i) ; } +#pragma omp master + { +#pragma omp target teams distribute simd // OK + for (int i = 0; i < 10; ++i) + ; + } // CRITICAL DIRECTIVE #pragma omp critical @@ -2310,6 +2359,12 @@ void foo() { for (int i = 0; i < 10; ++i) ; } +#pragma omp critical + { +#pragma omp target teams distribute simd // OK + for (int i = 0; i < 10; ++i) + ; + } // PARALLEL FOR DIRECTIVE #pragma omp parallel for @@ -2573,6 +2628,12 @@ void foo() { for (int j = 0; j < 10; ++j) ; } +#pragma omp parallel for + for (int i = 0; i < 10; ++i) { +#pragma omp target teams distribute simd // OK + for (int j = 0; j < 10; ++j) + ; + } // PARALLEL FOR SIMD DIRECTIVE #pragma omp parallel for simd @@ -2837,6 +2898,12 @@ void foo() { for (int j = 0; j < 10; ++j) ; } +#pragma omp parallel for simd + for (int i = 0; i < 10; ++i) { +#pragma omp target teams distribute simd // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int j = 0; j < 10; ++j) + ; + } // PARALLEL SECTIONS DIRECTIVE #pragma omp parallel sections @@ -3089,6 +3156,12 @@ void foo() { for (int i = 0; i < 10; ++i) ; } +#pragma omp parallel sections + { +#pragma omp target teams distribute simd // OK + for (int i = 0; i < 10; ++i) + ; + } // TASK DIRECTIVE #pragma omp task @@ -3288,6 +3361,12 @@ void foo() { for (int i = 0; i < 10; ++i) ; } +#pragma omp task + { +#pragma omp target teams distribute simd // OK + for (int i = 0; i < 10; ++i) + ; + } // ORDERED DIRECTIVE #pragma omp ordered @@ -3558,6 +3637,12 @@ void foo() { for (int i = 0; i < 10; ++i) ; } +#pragma omp ordered + { +#pragma omp target teams distribute simd // OK + for (int i = 0; i < 10; ++i) + ; + } // ATOMIC DIRECTIVE #pragma omp atomic @@ -3874,6 +3959,14 @@ void foo() { for (int i = 0; i < 10; ++i) ; } +#pragma omp atomic + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} + { +#pragma omp target teams distribute simd // expected-error {{OpenMP constructs may not be nested inside an atomic region}} + for (int i = 0; i < 10; ++i) + ; + } // TARGET DIRECTIVE #pragma omp target @@ -4090,6 +4183,12 @@ void foo() { for (int i = 0; i < 10; ++i) ; } +#pragma omp target + { +#pragma omp target teams distribute simd // expected-error {{region cannot be nested inside 'target' region}} + for (int i = 0; i < 10; ++i) + ; + } // TARGET PARALLEL DIRECTIVE #pragma omp target parallel @@ -4299,6 +4398,12 @@ void foo() { for (int i = 0; i < 10; ++i) ; } +#pragma omp target parallel + { +#pragma omp target teams distribute simd // expected-error {{region cannot be nested inside 'target parallel' region}} + for (int i = 0; i < 10; ++i) + ; + } // TARGET PARALLEL FOR DIRECTIVE #pragma omp target parallel for @@ -4562,6 +4667,12 @@ void foo() { for (int j = 0; j < 10; ++j) ; } +#pragma omp target parallel for + for (int i = 0; i < 10; ++i) { +#pragma omp target teams distribute simd // expected-error {{region cannot be nested inside 'target parallel for' region}} + for (int j = 0; j < 10; ++j) + ; + } // TEAMS DIRECTIVE #pragma omp teams // expected-error {{orphaned 'omp teams' directives are prohibited; perhaps you forget to enclose the directive into a target region?}} @@ -4824,6 +4935,13 @@ void foo() { for (int i = 0; i < 10; ++i) ; } +#pragma omp target +#pragma omp teams + { +#pragma omp target teams distribute simd // expected-error {{region cannot be nested inside 'target' region}} + for (int i = 0; i < 10; ++i) + ; + } // TASKLOOP DIRECTIVE #pragma omp taskloop @@ -5078,6 +5196,12 @@ void foo() { for (int j = 0; j < 10; ++j) ++a; } +#pragma omp taskloop + for (int i = 0; i < 10; ++i) { +#pragma omp target teams distribute simd // OK + for (int j = 0; j < 10; ++j) + ++a; + } // DISTRIBUTE DIRECTIVE #pragma omp target @@ -5374,6 +5498,14 @@ void foo() { for (int j = 0; j < 10; ++j) ; } +#pragma omp target +#pragma omp teams +#pragma omp distribute + for (int i = 0; i < 10; ++i) { +#pragma omp target teams distribute simd // expected-error {{region cannot be nested inside 'target' region}} + for (int j = 0; j < 10; ++j) + ; + } // DISTRIBUTE PARALLEL FOR DIRECTIVE #pragma omp target @@ -5678,6 +5810,14 @@ void foo() { for (int i = 0; i < 10; ++i) ; } +#pragma omp target +#pragma omp teams +#pragma omp distribute parallel for + for (int i = 0; i < 10; ++i) { +#pragma omp target teams distribute simd // expected-error {{region cannot be nested inside 'target' region}} + for (int i = 0; i < 10; ++i) + ; + } // DISTRIBUTE PARALLEL FOR SIMD DIRECTIVE #pragma omp target @@ -5990,6 +6130,14 @@ void foo() { for (int i = 0; i < 10; ++i) ++a; } +#pragma omp target +#pragma omp teams +#pragma omp distribute parallel for simd + for (int i = 0; i < 10; ++i) { +#pragma omp target teams distribute simd // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i) + ++a; + } // TARGET SIMD DIRECTIVE #pragma omp target simd @@ -6207,6 +6355,12 @@ void foo() { for (int i = 0; i < 10; ++i) ++a; } +#pragma omp target simd + for (int i = 0; i < 10; ++i) { +#pragma omp target teams distribute simd // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i) + ++a; + } // TEAMS DISTRIBUTE DIRECTIVE #pragma omp teams distribute // expected-error {{orphaned 'omp teams distribute' directives are prohibited; perhaps you forget to enclose the directive into a target region?}} @@ -6463,6 +6617,13 @@ void foo() { for (int i = 0; i < 10; ++i) ++a; } +#pragma omp target +#pragma omp teams distribute + for (int i = 0; i < 10; ++i) { +#pragma omp target teams distribute simd // expected-error {{region cannot be nested inside 'target' region}} + for (int i = 0; i < 10; ++i) + ++a; + } // TEAMS DISTRIBUTE DIRECTIVE #pragma omp teams distribute // expected-error {{orphaned 'omp teams distribute' directives are prohibited; perhaps you forget to enclose the directive into a target region?}} @@ -6739,6 +6900,13 @@ void foo() { for (int i = 0; i < 10; ++i) ++a; } +#pragma omp target +#pragma omp teams distribute + for (int i = 0; i < 10; ++i) { +#pragma omp target teams distribute simd // expected-error {{region cannot be nested inside 'target' region}} + for (int i = 0; i < 10; ++i) + ++a; + } // TEAMS DISTRIBUTE SIMD DIRECTIVE #pragma omp teams distribute simd // expected-error {{orphaned 'omp teams distribute simd' directives are prohibited; perhaps you forget to enclose the directive into a target region?}} @@ -7015,6 +7183,13 @@ void foo() { for (int i = 0; i < 10; ++i) ++a; } +#pragma omp target +#pragma omp teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp target teams distribute simd // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i) + ++a; + } // TEAMS DISTRIBUTE PARALLEL FOR SIMD DIRECTIVE #pragma omp teams distribute parallel for simd // expected-error {{orphaned 'omp teams distribute parallel for simd' directives are prohibited; perhaps you forget to enclose the directive into a target region?}} @@ -7291,6 +7466,13 @@ void foo() { for (int i = 0; i < 10; ++i) ++a; } +#pragma omp target +#pragma omp teams distribute parallel for simd + for (int i = 0; i < 10; ++i) { +#pragma omp target teams distribute simd // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i) + ++a; + } // TEAMS DISTRIBUTE PARALLEL FOR DIRECTIVE #pragma omp teams distribute parallel for // expected-error {{orphaned 'omp teams distribute parallel for' directives are prohibited; perhaps you forget to enclose the directive into a target region?}} @@ -7567,6 +7749,13 @@ void foo() { for (int i = 0; i < 10; ++i) ++a; } +#pragma omp target +#pragma omp teams distribute parallel for + for (int i = 0; i < 10; ++i) { +#pragma omp target teams distribute simd // expected-error {{region cannot be nested inside 'target' region}} + for (int i = 0; i < 10; ++i) + ++a; + } // TARGET TEAMS DIRECTIVE #pragma omp target teams @@ -7782,6 +7971,12 @@ void foo() { for (int i = 0; i < 10; ++i) ; } +#pragma omp target teams + { +#pragma omp target teams distribute simd // expected-error {{region cannot be nested inside 'target teams' region}} + for (int i = 0; i < 10; ++i) + ; + } // TARGET TEAMS DISTRIBUTE DIRECTIVE #pragma omp target teams distribute // OK @@ -8019,6 +8214,12 @@ void foo() { for (int i = 0; i < 10; ++i) ; } +#pragma omp target teams distribute + for (int i = 0; i < 10; ++i) { +#pragma omp target teams distribute simd // expected-error {{region cannot be nested inside 'target teams distribute' region}} + for (int i = 0; i < 10; ++i) + ; + } // TARGET TEAMS DISTRIBUTE PARALLEL FOR DIRECTIVE #pragma omp target teams distribute parallel for // OK @@ -8256,6 +8457,12 @@ void foo() { for (int i = 0; i < 10; ++i) ; } +#pragma omp target teams distribute parallel for + for (int i = 0; i < 10; ++i) { +#pragma omp target teams distribute simd // expected-error {{region cannot be nested inside 'target teams distribute parallel for' region}} + for (int i = 0; i < 10; ++i) + ; + } // TARGET TEAMS DISTRIBUTE PARALLEL FOR SIMD DIRECTIVE #pragma omp target teams distribute parallel for simd // OK @@ -8493,6 +8700,255 @@ void foo() { for (int i = 0; i < 10; ++i) ; } +#pragma omp target teams distribute parallel for simd + for (int i = 0; i < 10; ++i) { +#pragma omp target teams distribute simd // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i) + ; + } + +// TARGET TEAMS DISTRIBUTE SIMD DIRECTIVE +#pragma omp target teams distribute simd // OK + for (int i = 0; i < 10; ++i) + ; +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp distribute parallel for simd // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i) + ; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp distribute // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i) + ; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp for // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i) + ; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp simd // expected-warning {{OpenMP only allows an ordered construct with the simd clause nested in a simd construct}} + for (int i = 0; i < 10; ++i) + ; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp for simd // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i) + ; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp parallel // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i) + ; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp sections // expected-error {{OpenMP constructs may not be nested inside a simd region}} + { + bar(); + } + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp section // expected-error {{OpenMP constructs may not be nested inside a simd region}} + { + bar(); + } + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp single // expected-error {{OpenMP constructs may not be nested inside a simd region}} + { + bar(); + } + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp master // expected-error {{OpenMP constructs may not be nested inside a simd region}} + { + bar(); + } + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp critical // expected-error {{OpenMP constructs may not be nested inside a simd region}} + { + bar(); + } + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp parallel // expected-error {{OpenMP constructs may not be nested inside a simd region}} + { +#pragma omp single + { + bar(); + } + } + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i) + ; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp parallel for simd // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i) + ; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp parallel sections // expected-error {{OpenMP constructs may not be nested inside a simd region}} + { + bar(); + } + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp task // expected-error {{OpenMP constructs may not be nested inside a simd region}} + { + bar(); + } + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp taskyield // expected-error {{OpenMP constructs may not be nested inside a simd region}} + bar(); + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp barrier // expected-error {{OpenMP constructs may not be nested inside a simd region}} + bar(); + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp taskwait // expected-error {{OpenMP constructs may not be nested inside a simd region}} + bar(); + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp flush // expected-error {{OpenMP constructs may not be nested inside a simd region}} + bar(); + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp ordered // expected-error {{OpenMP constructs may not be nested inside a simd region}} + bar(); + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp atomic // expected-error {{OpenMP constructs may not be nested inside a simd region}}OK + ++a; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp target // expected-error {{OpenMP constructs may not be nested inside a simd region}} + ++a; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp target parallel // expected-error {{OpenMP constructs may not be nested inside a simd region}} + ++a; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp target parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i) + ; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp target enter data map(to: a) // expected-error {{OpenMP constructs may not be nested inside a simd region}} + ++a; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp target exit data map(from: a) // expected-error {{OpenMP constructs may not be nested inside a simd region}} + ++a; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp teams // expected-error {{OpenMP constructs may not be nested inside a simd region}} + ++a; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp target update to(a) // expected-error {{OpenMP constructs may not be nested inside a simd region}} + ++a; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp distribute simd // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i) + ++a; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp target simd // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i) + ++a; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp teams distribute // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i) + ++a; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp teams distribute simd // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i) + ++a; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp teams distribute parallel for simd // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i) + ++a; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp teams distribute parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i) + ; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp target teams // expected-error {{OpenMP constructs may not be nested inside a simd region}} + a++; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp target teams distribute // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i) + ; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp target teams distribute parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i) + ; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp target teams distribute parallel for simd // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i) + ; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp target teams distribute simd // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i) + ; + } } @@ -8700,6 +9156,12 @@ void foo() { for (int i = 0; i < 10; ++i) ; } +#pragma omp parallel + { +#pragma omp target teams distribute simd // OK + for (int i = 0; i < 10; ++i) + ; + } // SIMD DIRECTIVE #pragma omp simd @@ -8929,6 +9391,12 @@ void foo() { for (int j = 0; j < 10; ++j) ; } +#pragma omp simd + for (int i = 0; i < 10; ++i) { +#pragma omp target teams distribute simd // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int j = 0; j < 10; ++j) + ; + } // FOR DIRECTIVE #pragma omp for @@ -9178,6 +9646,12 @@ void foo() { for (int j = 0; j < 10; ++j) ; } +#pragma omp for + for (int i = 0; i < 10; ++i) { +#pragma omp target teams distribute simd // OK + for (int j = 0; j < 10; ++j) + ; + } // FOR SIMD DIRECTIVE #pragma omp for simd @@ -9407,6 +9881,12 @@ void foo() { for (int j = 0; j < 10; ++j) ; } +#pragma omp for simd + for (int i = 0; i < 10; ++i) { +#pragma omp target teams distribute simd // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int j = 0; j < 10; ++j) + ; + } // SECTIONS DIRECTIVE #pragma omp sections @@ -9645,6 +10125,12 @@ void foo() { for (int i = 0; i < 10; ++i) ; } +#pragma omp sections + { +#pragma omp target teams distribute simd // OK + for (int i = 0; i < 10; ++i) + ; + } // SECTION DIRECTIVE #pragma omp section // expected-error {{orphaned 'omp section' directives are prohibited, it must be closely nested to a sections region}} @@ -9984,6 +10470,13 @@ void foo() { for (int i = 0; i < 10; ++i) ; } +#pragma omp sections + { +#pragma omp section +#pragma omp target teams distribute simd // OK + for (int i = 0; i < 10; ++i) + ; + } // SINGLE DIRECTIVE #pragma omp single @@ -10223,6 +10716,12 @@ void foo() { for (int i = 0; i < 10; ++i) ; } +#pragma omp single + { +#pragma omp target teams distribute simd // OK + for (int i = 0; i < 10; ++i) + ; + } // MASTER DIRECTIVE #pragma omp master @@ -10472,6 +10971,12 @@ void foo() { for (int i = 0; i < 10; ++i) ; } +#pragma omp master + { +#pragma omp target teams distribute simd // OK + for (int i = 0; i < 10; ++i) + ; + } // CRITICAL DIRECTIVE #pragma omp critical @@ -10740,6 +11245,12 @@ void foo() { for (int i = 0; i < 10; ++i) ; } +#pragma omp critical + { +#pragma omp target teams distribute simd // OK + for (int i = 0; i < 10; ++i) + ; + } // PARALLEL FOR DIRECTIVE #pragma omp parallel for @@ -11004,6 +11515,12 @@ void foo() { for (int j = 0; j < 10; ++j) ; } +#pragma omp parallel for + for (int i = 0; i < 10; ++i) { +#pragma omp target teams distribute simd // OK + for (int j = 0; j < 10; ++j) + ; + } // PARALLEL FOR SIMD DIRECTIVE #pragma omp parallel for simd @@ -11268,6 +11785,12 @@ void foo() { for (int j = 0; j < 10; ++j) ; } +#pragma omp parallel for simd + for (int i = 0; i < 10; ++i) { +#pragma omp target teams distribute simd // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int j = 0; j < 10; ++j) + ; + } // PARALLEL SECTIONS DIRECTIVE #pragma omp parallel sections @@ -11516,6 +12039,12 @@ void foo() { for (int i = 0; i < 10; ++i) ; } +#pragma omp parallel sections + { +#pragma omp target teams distribute simd // OK + for (int i = 0; i < 10; ++i) + ; + } // TASK DIRECTIVE #pragma omp task @@ -11714,6 +12243,12 @@ void foo() { for (int i = 0; i < 10; ++i) ; } +#pragma omp task + { +#pragma omp target teams distribute simd // OK + for (int i = 0; i < 10; ++i) + ; + } // ATOMIC DIRECTIVE #pragma omp atomic @@ -12029,6 +12564,14 @@ void foo() { for (int i = 0; i < 10; ++i) ; } +#pragma omp atomic + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} + { +#pragma omp target teams distribute simd // expected-error {{OpenMP constructs may not be nested inside an atomic region}} + for (int i = 0; i < 10; ++i) + ; + } // TARGET DIRECTIVE #pragma omp target @@ -12241,6 +12784,12 @@ void foo() { for (int i = 0; i < 10; ++i) ; } +#pragma omp target + { +#pragma omp target teams distribute simd // expected-error {{region cannot be nested inside 'target' region}} + for (int i = 0; i < 10; ++i) + ; + } // TARGET PARALLEL DIRECTIVE #pragma omp target parallel @@ -12450,6 +12999,12 @@ void foo() { for (int i = 0; i < 10; ++i) ; } +#pragma omp target parallel + { +#pragma omp target teams distribute simd // expected-error {{region cannot be nested inside 'target parallel' region}} + for (int i = 0; i < 10; ++i) + ; + } // TARGET PARALLEL FOR DIRECTIVE #pragma omp target parallel for @@ -12714,6 +13269,12 @@ void foo() { for (int j = 0; j < 10; ++j) ; } +#pragma omp target parallel for + for (int i = 0; i < 10; ++i) { +#pragma omp target teams distribute simd // expected-error {{region cannot be nested inside 'target parallel for' region}} + for (int j = 0; j < 10; ++j) + ; + } // TEAMS DIRECTIVE #pragma omp target @@ -12978,6 +13539,13 @@ void foo() { for (int i = 0; i < 10; ++i) ; } +#pragma omp target +#pragma omp teams + { +#pragma omp target teams distribute simd // expected-error {{region cannot be nested inside 'target' region}} + for (int i = 0; i < 10; ++i) + ; + } // TASKLOOP DIRECTIVE #pragma omp taskloop @@ -13232,6 +13800,12 @@ void foo() { for (int i = 0; i < 10; ++i) ; } +#pragma omp taskloop + for (int i = 0; i < 10; ++i) { +#pragma omp target teams distribute simd // OK + for (int i = 0; i < 10; ++i) + ; + } // DISTRIBUTE DIRECTIVE #pragma omp target @@ -13537,6 +14111,14 @@ void foo() { for (int i = 0; i < 10; ++i) ++a; } +#pragma omp target +#pragma omp teams +#pragma omp distribute + for (int i = 0; i < 10; ++i) { +#pragma omp target teams distribute simd // expected-error {{region cannot be nested inside 'target' region}} + for (int i = 0; i < 10; ++i) + ++a; + } // DISTRIBUTE PARALLEL FOR DIRECTIVE #pragma omp target @@ -13850,6 +14432,14 @@ void foo() { for (int i = 0; i < 10; ++i) ++a; } +#pragma omp target +#pragma omp teams +#pragma omp distribute parallel for + for (int i = 0; i < 10; ++i) { +#pragma omp target teams distribute simd // expected-error {{region cannot be nested inside 'target' region}} + for (int i = 0; i < 10; ++i) + ++a; + } // DISTRIBUTE PARALLEL FOR SIMD DIRECTIVE #pragma omp target @@ -14154,6 +14744,14 @@ void foo() { for (int i = 0; i < 10; ++i) ; } +#pragma omp target +#pragma omp teams +#pragma omp distribute parallel for simd + for (int i = 0; i < 10; ++i) { +#pragma omp target teams distribute simd // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i) + ; + } // DISTRIBUTE SIMD DIRECTIVE #pragma omp target @@ -14458,6 +15056,14 @@ void foo() { for (int i = 0; i < 10; ++i) ; } +#pragma omp target +#pragma omp teams +#pragma omp distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp target teams distribute simd // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i) + ; + } // TARGET SIMD DIRECTIVE #pragma omp target simd @@ -14686,6 +15292,12 @@ void foo() { for (int i = 0; i < 10; ++i) ; } +#pragma omp target simd + for (int i = 0; i < 10; ++i) { +#pragma omp target teams distribute simd // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i) + ; + } // TEAMS DISTRIBUTE DIRECTIVE #pragma omp teams distribute // expected-error {{orphaned 'omp teams distribute' directives are prohibited; perhaps you forget to enclose the directive into a target region?}} @@ -14962,6 +15574,13 @@ void foo() { for (int i = 0; i < 10; ++i) ++a; } +#pragma omp target +#pragma omp teams distribute + for (int i = 0; i < 10; ++i) { +#pragma omp target teams distribute simd // expected-error {{region cannot be nested inside 'target' region}} + for (int i = 0; i < 10; ++i) + ++a; + } // TEAMS DISTRIBUTE SIMD DIRECTIVE #pragma omp teams distribute simd // expected-error {{orphaned 'omp teams distribute simd' directives are prohibited; perhaps you forget to enclose the directive into a target region?}} @@ -15238,6 +15857,13 @@ void foo() { for (int i = 0; i < 10; ++i) ++a; } +#pragma omp target +#pragma omp teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp target teams distribute simd // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i) + ++a; + } // TEAMS DISTRIBUTE PARALLEL FOR SIMD DIRECTIVE #pragma omp teams distribute parallel for simd // expected-error {{orphaned 'omp teams distribute parallel for simd' directives are prohibited; perhaps you forget to enclose the directive into a target region?}} @@ -15514,6 +16140,13 @@ void foo() { for (int i = 0; i < 10; ++i) ++a; } +#pragma omp target +#pragma omp teams distribute parallel for simd + for (int i = 0; i < 10; ++i) { +#pragma omp target teams distribute simd // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i) + ++a; + } // TEAMS DISTRIBUTE PARALLEL FOR DIRECTIVE #pragma omp teams distribute parallel for // expected-error {{orphaned 'omp teams distribute parallel for' directives are prohibited; perhaps you forget to enclose the directive into a target region?}} @@ -15790,6 +16423,13 @@ void foo() { for (int i = 0; i < 10; ++i) ++a; } +#pragma omp target +#pragma omp teams distribute parallel for + for (int i = 0; i < 10; ++i) { +#pragma omp target teams distribute simd // expected-error {{region cannot be nested inside 'target' region}} + for (int i = 0; i < 10; ++i) + ++a; + } // TARGET TEAMS DIRECTIVE #pragma omp target teams @@ -16005,6 +16645,12 @@ void foo() { for (int i = 0; i < 10; ++i) ; } +#pragma omp target teams + { +#pragma omp target teams distribute simd // expected-error {{region cannot be nested inside 'target teams' region}} + for (int i = 0; i < 10; ++i) + ; + } // TARGET TEAMS DISTRIBUTE DIRECTIVE #pragma omp target teams distribute // OK @@ -16242,6 +16888,12 @@ void foo() { for (int i = 0; i < 10; ++i) ++a; } +#pragma omp target teams distribute + for (int i = 0; i < 10; ++i) { +#pragma omp target teams distribute simd // expected-error {{region cannot be nested inside 'target teams distribute' region}} + for (int i = 0; i < 10; ++i) + ++a; + } // TARGET TEAMS DISTRIBUTE PARALLEL FOR DIRECTIVE #pragma omp target teams distribute parallel for // OK @@ -16479,6 +17131,12 @@ void foo() { for (int i = 0; i < 10; ++i) ++a; } +#pragma omp target teams distribute parallel for + for (int i = 0; i < 10; ++i) { +#pragma omp target teams distribute simd // expected-error {{region cannot be nested inside 'target teams distribute parallel for' region}} + for (int i = 0; i < 10; ++i) + ++a; + } // TARGET TEAMS DISTRIBUTE PARALLEL FOR SIMD DIRECTIVE #pragma omp target teams distribute parallel for simd // OK @@ -16716,7 +17374,256 @@ void foo() { for (int i = 0; i < 10; ++i) ; } - +#pragma omp target teams distribute parallel for simd + for (int i = 0; i < 10; ++i) { +#pragma omp target teams distribute simd // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i) + ; + } + +// TARGET TEAMS DISTRIBUTE SIMD DIRECTIVE +#pragma omp target teams distribute simd // OK + for (int i = 0; i < 10; ++i) + ; +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp distribute parallel for simd // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i) + ; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp distribute // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i) + ; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp for // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i) + ; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp simd // expected-warning {{OpenMP only allows an ordered construct with the simd clause nested in a simd construct}} + for (int i = 0; i < 10; ++i) + ; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp for simd // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i) + ; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp parallel // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i) + ; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp sections // expected-error {{OpenMP constructs may not be nested inside a simd region}} + { + bar(); + } + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp section // expected-error {{OpenMP constructs may not be nested inside a simd region}} + { + bar(); + } + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp single // expected-error {{OpenMP constructs may not be nested inside a simd region}} + { + bar(); + } + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp master // expected-error {{OpenMP constructs may not be nested inside a simd region}} + { + bar(); + } + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp critical // expected-error {{OpenMP constructs may not be nested inside a simd region}} + { + bar(); + } + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp parallel // expected-error {{OpenMP constructs may not be nested inside a simd region}} + { +#pragma omp single + { + bar(); + } + } + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i) + ; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp parallel for simd // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i) + ; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp parallel sections // expected-error {{OpenMP constructs may not be nested inside a simd region}} + { + bar(); + } + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp task // expected-error {{OpenMP constructs may not be nested inside a simd region}} + { + bar(); + } + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp taskyield // expected-error {{OpenMP constructs may not be nested inside a simd region}} + bar(); + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp barrier // expected-error {{OpenMP constructs may not be nested inside a simd region}} + bar(); + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp taskwait // expected-error {{OpenMP constructs may not be nested inside a simd region}} + bar(); + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp flush // expected-error {{OpenMP constructs may not be nested inside a simd region}} + bar(); + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp ordered // expected-error {{OpenMP constructs may not be nested inside a simd region}} + bar(); + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp atomic // expected-error {{OpenMP constructs may not be nested inside a simd region}}OK + ++a; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp target // expected-error {{OpenMP constructs may not be nested inside a simd region}} + ++a; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp target parallel // expected-error {{OpenMP constructs may not be nested inside a simd region}} + ++a; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp target parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i) + ; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp target enter data map(to: a) // expected-error {{OpenMP constructs may not be nested inside a simd region}} + ++a; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp target exit data map(from: a) // expected-error {{OpenMP constructs may not be nested inside a simd region}} + ++a; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp teams // expected-error {{OpenMP constructs may not be nested inside a simd region}} + ++a; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp target update to(a) // expected-error {{OpenMP constructs may not be nested inside a simd region}} + ++a; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp distribute simd // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i) + ++a; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp target simd // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i) + ++a; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp teams distribute // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i) + ++a; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp teams distribute simd // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i) + ++a; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp teams distribute parallel for simd // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i) + ++a; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp teams distribute parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i) + ; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp target teams // expected-error {{OpenMP constructs may not be nested inside a simd region}} + a++; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp target teams distribute // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i) + ; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp target teams distribute parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i) + ; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp target teams distribute parallel for simd // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i) + ; + } +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { +#pragma omp target teams distribute simd // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i) + ; + } + return foo<int>(); } diff --git a/test/OpenMP/nvptx_parallel_codegen.cpp b/test/OpenMP/nvptx_parallel_codegen.cpp new file mode 100644 index 000000000000..224f24569669 --- /dev/null +++ b/test/OpenMP/nvptx_parallel_codegen.cpp @@ -0,0 +1,317 @@ +// Test target codegen - host bc file has to be created first. +// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc +// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 +// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm-bc %s -o %t-x86-host.bc +// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 +// RUN: %clang_cc1 -verify -fopenmp -fexceptions -fcxx-exceptions -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 +// expected-no-diagnostics +#ifndef HEADER +#define HEADER + +template<typename tx> +tx ftemplate(int n) { + tx a = 0; + short aa = 0; + tx b[10]; + + #pragma omp target if(0) + { + #pragma omp parallel + { + int a = 41; + } + a += 1; + } + + #pragma omp target + { + #pragma omp parallel + { + int a = 42; + } + #pragma omp parallel if(0) + { + int a = 43; + } + #pragma omp parallel if(1) + { + int a = 44; + } + a += 1; + } + + #pragma omp target if(n>40) + { + #pragma omp parallel if(n>1000) + { + int a = 45; + } + a += 1; + aa += 1; + b[2] += 1; + } + + return a; +} + +int bar(int n){ + int a = 0; + + a += ftemplate<int>(n); + + return a; +} + + // CHECK-NOT: define {{.*}}void {{@__omp_offloading_.+template.+l17}}_worker() + + + + + + + // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l26}}_worker() + // CHECK-DAG: [[OMP_EXEC_STATUS:%.+]] = alloca i8, + // CHECK-DAG: [[OMP_WORK_FN:%.+]] = alloca i8*, + // CHECK: store i8* null, i8** [[OMP_WORK_FN]], + // CHECK: store i8 0, i8* [[OMP_EXEC_STATUS]], + // CHECK: br label {{%?}}[[AWAIT_WORK:.+]] + // + // CHECK: [[AWAIT_WORK]] + // CHECK: call void @llvm.nvvm.barrier0() + // CHECK: [[KPR:%.+]] = call i1 @__kmpc_kernel_parallel(i8** [[OMP_WORK_FN]]) + // CHECK: [[KPRB:%.+]] = zext i1 [[KPR]] to i8 + // store i8 [[KPRB]], i8* [[OMP_EXEC_STATUS]], align 1 + // CHECK: [[WORK:%.+]] = load i8*, i8** [[OMP_WORK_FN]], + // CHECK: [[SHOULD_EXIT:%.+]] = icmp eq i8* [[WORK]], null + // CHECK: br i1 [[SHOULD_EXIT]], label {{%?}}[[EXIT:.+]], label {{%?}}[[SEL_WORKERS:.+]] + // + // CHECK: [[SEL_WORKERS]] + // CHECK: [[ST:%.+]] = load i8, i8* [[OMP_EXEC_STATUS]] + // CHECK: [[IS_ACTIVE:%.+]] = icmp ne i8 [[ST]], 0 + // CHECK: br i1 [[IS_ACTIVE]], label {{%?}}[[EXEC_PARALLEL:.+]], label {{%?}}[[BAR_PARALLEL:.+]] + // + // CHECK: [[EXEC_PARALLEL]] + // CHECK: [[WF1:%.+]] = load i8*, i8** [[OMP_WORK_FN]], + // CHECK: [[WM1:%.+]] = icmp eq i8* [[WF1]], bitcast (void (i32*, i32*)* [[PARALLEL_FN1:@.+]] to i8*) + // CHECK: br i1 [[WM1]], label {{%?}}[[EXEC_PFN1:.+]], label {{%?}}[[CHECK_NEXT1:.+]] + // + // CHECK: [[EXEC_PFN1]] + // CHECK: call void [[PARALLEL_FN1]]( + // CHECK: br label {{%?}}[[TERM_PARALLEL:.+]] + // + // CHECK: [[CHECK_NEXT1]] + // CHECK: [[WF2:%.+]] = load i8*, i8** [[OMP_WORK_FN]], + // CHECK: [[WM2:%.+]] = icmp eq i8* [[WF2]], bitcast (void (i32*, i32*)* [[PARALLEL_FN2:@.+]] to i8*) + // CHECK: br i1 [[WM2]], label {{%?}}[[EXEC_PFN2:.+]], label {{%?}}[[CHECK_NEXT2:.+]] + // + // CHECK: [[EXEC_PFN2]] + // CHECK: call void [[PARALLEL_FN2]]( + // CHECK: br label {{%?}}[[TERM_PARALLEL:.+]] + // + // CHECK: [[CHECK_NEXT2]] + // CHECK: br label {{%?}}[[TERM_PARALLEL:.+]] + // + // CHECK: [[TERM_PARALLEL]] + // CHECK: call void @__kmpc_kernel_end_parallel() + // CHECK: br label {{%?}}[[BAR_PARALLEL]] + // + // CHECK: [[BAR_PARALLEL]] + // CHECK: call void @llvm.nvvm.barrier0() + // CHECK: br label {{%?}}[[AWAIT_WORK]] + // + // CHECK: [[EXIT]] + // CHECK: ret void + + // CHECK: define {{.*}}void [[T6:@__omp_offloading_.+template.+l26]](i[[SZ:32|64]] + // Create local storage for each capture. + // CHECK: [[LOCAL_A:%.+]] = alloca i[[SZ]], + // CHECK-DAG: store i[[SZ]] [[ARG_A:%.+]], i[[SZ]]* [[LOCAL_A]] + // Store captures in the context. + // CHECK-64-DAG:[[REF_A:%.+]] = bitcast i[[SZ]]* [[LOCAL_A]] to i32* + // + // CHECK-DAG: [[TID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.tid.x() + // CHECK-DAG: [[NTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x() + // CHECK-DAG: [[WS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize() + // CHECK-DAG: [[TH_LIMIT:%.+]] = sub i32 [[NTH]], [[WS]] + // CHECK: [[IS_WORKER:%.+]] = icmp ult i32 [[TID]], [[TH_LIMIT]] + // CHECK: br i1 [[IS_WORKER]], label {{%?}}[[WORKER:.+]], label {{%?}}[[CHECK_MASTER:.+]] + // + // CHECK: [[WORKER]] + // CHECK: {{call|invoke}} void [[T6]]_worker() + // CHECK: br label {{%?}}[[EXIT:.+]] + // + // CHECK: [[CHECK_MASTER]] + // CHECK-DAG: [[CMTID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.tid.x() + // CHECK-DAG: [[CMNTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x() + // CHECK-DAG: [[CMWS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize() + // CHECK: [[IS_MASTER:%.+]] = icmp eq i32 [[CMTID]], + // CHECK: br i1 [[IS_MASTER]], label {{%?}}[[MASTER:.+]], label {{%?}}[[EXIT]] + // + // CHECK: [[MASTER]] + // CHECK-DAG: [[MNTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x() + // CHECK-DAG: [[MWS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize() + // CHECK: [[MTMP1:%.+]] = sub i32 [[MNTH]], [[MWS]] + // CHECK: call void @__kmpc_kernel_init(i32 [[MTMP1]] + // CHECK: call void @__kmpc_kernel_prepare_parallel(i8* bitcast (void (i32*, i32*)* [[PARALLEL_FN1]] to i8*)) + // CHECK: call void @llvm.nvvm.barrier0() + // CHECK: call void @llvm.nvvm.barrier0() + // CHECK: call void @__kmpc_serialized_parallel( + // CHECK: {{call|invoke}} void [[PARALLEL_FN3:@.+]]( + // CHECK: call void @__kmpc_end_serialized_parallel( + // CHECK: call void @__kmpc_kernel_prepare_parallel(i8* bitcast (void (i32*, i32*)* [[PARALLEL_FN2]] to i8*)) + // CHECK: call void @llvm.nvvm.barrier0() + // CHECK: call void @llvm.nvvm.barrier0() + // CHECK-64-DAG: load i32, i32* [[REF_A]] + // CHECK-32-DAG: load i32, i32* [[LOCAL_A]] + // CHECK: br label {{%?}}[[TERMINATE:.+]] + // + // CHECK: [[TERMINATE]] + // CHECK: call void @__kmpc_kernel_deinit() + // CHECK: call void @llvm.nvvm.barrier0() + // CHECK: br label {{%?}}[[EXIT]] + // + // CHECK: [[EXIT]] + // CHECK: ret void + + // CHECK-DAG: define internal void [[PARALLEL_FN1]]( + // CHECK: [[A:%.+]] = alloca i[[SZ:32|64]], + // CHECK: store i[[SZ]] 42, i[[SZ]]* %a, + // CHECK: ret void + + // CHECK-DAG: define internal void [[PARALLEL_FN3]]( + // CHECK: [[A:%.+]] = alloca i[[SZ:32|64]], + // CHECK: store i[[SZ]] 43, i[[SZ]]* %a, + // CHECK: ret void + + // CHECK-DAG: define internal void [[PARALLEL_FN2]]( + // CHECK: [[A:%.+]] = alloca i[[SZ:32|64]], + // CHECK: store i[[SZ]] 44, i[[SZ]]* %a, + // CHECK: ret void + + + + + + + + // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l43}}_worker() + // CHECK-DAG: [[OMP_EXEC_STATUS:%.+]] = alloca i8, + // CHECK-DAG: [[OMP_WORK_FN:%.+]] = alloca i8*, + // CHECK: store i8* null, i8** [[OMP_WORK_FN]], + // CHECK: store i8 0, i8* [[OMP_EXEC_STATUS]], + // CHECK: br label {{%?}}[[AWAIT_WORK:.+]] + // + // CHECK: [[AWAIT_WORK]] + // CHECK: call void @llvm.nvvm.barrier0() + // CHECK: [[KPR:%.+]] = call i1 @__kmpc_kernel_parallel(i8** [[OMP_WORK_FN]]) + // CHECK: [[KPRB:%.+]] = zext i1 [[KPR]] to i8 + // store i8 [[KPRB]], i8* [[OMP_EXEC_STATUS]], align 1 + // CHECK: [[WORK:%.+]] = load i8*, i8** [[OMP_WORK_FN]], + // CHECK: [[SHOULD_EXIT:%.+]] = icmp eq i8* [[WORK]], null + // CHECK: br i1 [[SHOULD_EXIT]], label {{%?}}[[EXIT:.+]], label {{%?}}[[SEL_WORKERS:.+]] + // + // CHECK: [[SEL_WORKERS]] + // CHECK: [[ST:%.+]] = load i8, i8* [[OMP_EXEC_STATUS]] + // CHECK: [[IS_ACTIVE:%.+]] = icmp ne i8 [[ST]], 0 + // CHECK: br i1 [[IS_ACTIVE]], label {{%?}}[[EXEC_PARALLEL:.+]], label {{%?}}[[BAR_PARALLEL:.+]] + // + // CHECK: [[EXEC_PARALLEL]] + // CHECK: [[WF:%.+]] = load i8*, i8** [[OMP_WORK_FN]], + // CHECK: [[WM:%.+]] = icmp eq i8* [[WF]], bitcast (void (i32*, i32*)* [[PARALLEL_FN4:@.+]] to i8*) + // CHECK: br i1 [[WM]], label {{%?}}[[EXEC_PFN:.+]], label {{%?}}[[CHECK_NEXT:.+]] + // + // CHECK: [[EXEC_PFN]] + // CHECK: call void [[PARALLEL_FN4]]( + // CHECK: br label {{%?}}[[TERM_PARALLEL:.+]] + // + // CHECK: [[CHECK_NEXT]] + // CHECK: br label {{%?}}[[TERM_PARALLEL:.+]] + // + // CHECK: [[TERM_PARALLEL]] + // CHECK: call void @__kmpc_kernel_end_parallel() + // CHECK: br label {{%?}}[[BAR_PARALLEL]] + // + // CHECK: [[BAR_PARALLEL]] + // CHECK: call void @llvm.nvvm.barrier0() + // CHECK: br label {{%?}}[[AWAIT_WORK]] + // + // CHECK: [[EXIT]] + // CHECK: ret void + + // CHECK: define {{.*}}void [[T6:@__omp_offloading_.+template.+l43]](i[[SZ:32|64]] + // Create local storage for each capture. + // CHECK: [[LOCAL_N:%.+]] = alloca i[[SZ]], + // CHECK: [[LOCAL_A:%.+]] = alloca i[[SZ]], + // CHECK: [[LOCAL_AA:%.+]] = alloca i[[SZ]], + // CHECK: [[LOCAL_B:%.+]] = alloca [10 x i32]* + // CHECK-DAG: store i[[SZ]] [[ARG_N:%.+]], i[[SZ]]* [[LOCAL_N]] + // CHECK-DAG: store i[[SZ]] [[ARG_A:%.+]], i[[SZ]]* [[LOCAL_A]] + // CHECK-DAG: store i[[SZ]] [[ARG_AA:%.+]], i[[SZ]]* [[LOCAL_AA]] + // CHECK-DAG: store [10 x i32]* [[ARG_B:%.+]], [10 x i32]** [[LOCAL_B]] + // Store captures in the context. + // CHECK-64-DAG:[[REF_N:%.+]] = bitcast i[[SZ]]* [[LOCAL_N]] to i32* + // CHECK-64-DAG:[[REF_A:%.+]] = bitcast i[[SZ]]* [[LOCAL_A]] to i32* + // CHECK-DAG: [[REF_AA:%.+]] = bitcast i[[SZ]]* [[LOCAL_AA]] to i16* + // CHECK-DAG: [[REF_B:%.+]] = load [10 x i32]*, [10 x i32]** [[LOCAL_B]], + // + // CHECK-DAG: [[TID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.tid.x() + // CHECK-DAG: [[NTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x() + // CHECK-DAG: [[WS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize() + // CHECK-DAG: [[TH_LIMIT:%.+]] = sub i32 [[NTH]], [[WS]] + // CHECK: [[IS_WORKER:%.+]] = icmp ult i32 [[TID]], [[TH_LIMIT]] + // CHECK: br i1 [[IS_WORKER]], label {{%?}}[[WORKER:.+]], label {{%?}}[[CHECK_MASTER:.+]] + // + // CHECK: [[WORKER]] + // CHECK: {{call|invoke}} void [[T6]]_worker() + // CHECK: br label {{%?}}[[EXIT:.+]] + // + // CHECK: [[CHECK_MASTER]] + // CHECK-DAG: [[CMTID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.tid.x() + // CHECK-DAG: [[CMNTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x() + // CHECK-DAG: [[CMWS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize() + // CHECK: [[IS_MASTER:%.+]] = icmp eq i32 [[CMTID]], + // CHECK: br i1 [[IS_MASTER]], label {{%?}}[[MASTER:.+]], label {{%?}}[[EXIT]] + // + // CHECK: [[MASTER]] + // CHECK-DAG: [[MNTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x() + // CHECK-DAG: [[MWS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize() + // CHECK: [[MTMP1:%.+]] = sub i32 [[MNTH]], [[MWS]] + // CHECK: call void @__kmpc_kernel_init(i32 [[MTMP1]] + // CHECK-64: [[N:%.+]] = load i32, i32* [[REF_N]], + // CHECK-32: [[N:%.+]] = load i32, i32* [[LOCAL_N]], + // CHECK: [[CMP:%.+]] = icmp sgt i32 [[N]], 1000 + // CHECK: br i1 [[CMP]], label {{%?}}[[IF_THEN:.+]], label {{%?}}[[IF_ELSE:.+]] + // + // CHECK: [[IF_THEN]] + // CHECK: call void @__kmpc_kernel_prepare_parallel(i8* bitcast (void (i32*, i32*)* [[PARALLEL_FN4]] to i8*)) + // CHECK: call void @llvm.nvvm.barrier0() + // CHECK: call void @llvm.nvvm.barrier0() + // CHECK: br label {{%?}}[[IF_END:.+]] + // + // CHECK: [[IF_ELSE]] + // CHECK: call void @__kmpc_serialized_parallel( + // CHECK: {{call|invoke}} void [[PARALLEL_FN4]]( + // CHECK: call void @__kmpc_end_serialized_parallel( + // br label [[IF_END]] + // + // CHECK: [[IF_END]] + // CHECK-64-DAG: load i32, i32* [[REF_A]] + // CHECK-32-DAG: load i32, i32* [[LOCAL_A]] + // CHECK-DAG: load i16, i16* [[REF_AA]] + // CHECK-DAG: getelementptr inbounds [10 x i32], [10 x i32]* [[REF_B]], i[[SZ]] 0, i[[SZ]] 2 + // + // CHECK: br label {{%?}}[[TERMINATE:.+]] + // + // CHECK: [[TERMINATE]] + // CHECK: call void @__kmpc_kernel_deinit() + // CHECK: call void @llvm.nvvm.barrier0() + // CHECK: br label {{%?}}[[EXIT]] + // + // CHECK: [[EXIT]] + // CHECK: ret void + + // CHECK: define internal void [[PARALLEL_FN4]]( + // CHECK: [[A:%.+]] = alloca i[[SZ:32|64]], + // CHECK: store i[[SZ]] 45, i[[SZ]]* %a, + // CHECK: ret void +#endif diff --git a/test/OpenMP/target_parallel_for_is_device_ptr_ast_print.cpp b/test/OpenMP/target_parallel_for_is_device_ptr_ast_print.cpp new file mode 100644 index 000000000000..eaa0941a388e --- /dev/null +++ b/test/OpenMP/target_parallel_for_is_device_ptr_ast_print.cpp @@ -0,0 +1,315 @@ +// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ast-print %s | FileCheck %s +// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s +// expected-no-diagnostics + +#ifndef HEADER +#define HEADER + +void foo() {} + +struct ST { + int *a; +}; +typedef int arr[10]; +typedef ST STarr[10]; +struct SA { + const int da[5] = { 0 }; + ST g[10]; + STarr &rg = g; + int i; + int &j = i; + int *k = &j; + int *&z = k; + int aa[10]; + arr &raa = aa; + void func(int arg) { +#pragma omp target parallel for is_device_ptr(k) + for (int i=0; i<100; i++) foo(); + +#pragma omp target parallel for is_device_ptr(z) + for (int i=0; i<100; i++) foo(); + +#pragma omp target parallel for is_device_ptr(aa) // OK + for (int i=0; i<100; i++) foo(); + +#pragma omp target parallel for is_device_ptr(raa) // OK + for (int i=0; i<100; i++) foo(); + +#pragma omp target parallel for is_device_ptr(g) // OK + for (int i=0; i<100; i++) foo(); + +#pragma omp target parallel for is_device_ptr(rg) // OK + for (int i=0; i<100; i++) foo(); + +#pragma omp target parallel for is_device_ptr(da) // OK + for (int i=0; i<100; i++) foo(); + + return; + } +}; +// CHECK: struct SA +// CHECK-NEXT: const int da[5] = {0}; +// CHECK-NEXT: ST g[10]; +// CHECK-NEXT: STarr &rg = this->g; +// CHECK-NEXT: int i; +// CHECK-NEXT: int &j = this->i; +// CHECK-NEXT: int *k = &this->j; +// CHECK-NEXT: int *&z = this->k; +// CHECK-NEXT: int aa[10]; +// CHECK-NEXT: arr &raa = this->aa; +// CHECK-NEXT: func( +// CHECK-NEXT: #pragma omp target parallel for is_device_ptr(this->k) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: foo(); +// CHECK-NEXT: #pragma omp target parallel for is_device_ptr(this->z) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: foo(); +// CHECK-NEXT: #pragma omp target parallel for is_device_ptr(this->aa) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: foo(); +// CHECK-NEXT: #pragma omp target parallel for is_device_ptr(this->raa) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: foo(); +// CHECK-NEXT: #pragma omp target parallel for is_device_ptr(this->g) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: foo(); +// CHECK-NEXT: #pragma omp target parallel for is_device_ptr(this->rg) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: foo(); +// CHECK-NEXT: #pragma omp target parallel for is_device_ptr(this->da) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: foo(); + +struct SB { + unsigned A; + unsigned B; + float Arr[100]; + float *Ptr; + float *foo() { + return &Arr[0]; + } +}; + +struct SC { + unsigned A : 2; + unsigned B : 3; + unsigned C; + unsigned D; + float Arr[100]; + SB S; + SB ArrS[100]; + SB *PtrS; + SB *&RPtrS; + float *Ptr; + + SC(SB *&_RPtrS) : RPtrS(_RPtrS) {} +}; + +union SD { + unsigned A; + float B; +}; + +struct S1; +extern S1 a; +class S2 { + mutable int a; +public: + S2():a(0) { } + S2(S2 &s2):a(s2.a) { } + static float S2s; + static const float S2sc; +}; +const float S2::S2sc = 0; +const S2 b; +const S2 ba[5]; +class S3 { + int a; +public: + S3():a(0) { } + S3(S3 &s3):a(s3.a) { } +}; +const S3 c; +const S3 ca[5]; +extern const int f; +class S4 { + int a; + S4(); + S4(const S4 &s4); +public: + S4(int v):a(v) { } +}; +class S5 { + int a; + S5():a(0) {} + S5(const S5 &s5):a(s5.a) { } +public: + S5(int v):a(v) { } +}; + +S3 h; +#pragma omp threadprivate(h) + +typedef struct { + int a; +} S6; + +template <typename T> +T tmain(T argc) { + const T da[5] = { 0 }; + S6 h[10]; + auto &rh = h; + T i; + T &j = i; + T *k = &j; + T *&z = k; + T aa[10]; + auto &raa = aa; +#pragma omp target parallel for is_device_ptr(k) + for (int i=0; i<100; i++) foo(); +#pragma omp target parallel for is_device_ptr(z) + for (int i=0; i<100; i++) foo(); +#pragma omp target parallel for is_device_ptr(aa) + for (int i=0; i<100; i++) foo(); +#pragma omp target parallel for is_device_ptr(raa) + for (int i=0; i<100; i++) foo(); +#pragma omp target parallel for is_device_ptr(h) + for (int i=0; i<100; i++) foo(); +#pragma omp target parallel for is_device_ptr(rh) + for (int i=0; i<100; i++) foo(); +#pragma omp target parallel for is_device_ptr(da) + for (int i=0; i<100; i++) foo(); + return 0; +} + +// CHECK: template<> int tmain<int>(int argc) { +// CHECK-NEXT: const int da[5] = {0}; +// CHECK-NEXT: S6 h[10]; +// CHECK-NEXT: auto &rh = h; +// CHECK-NEXT: int i; +// CHECK-NEXT: int &j = i; +// CHECK-NEXT: int *k = &j; +// CHECK-NEXT: int *&z = k; +// CHECK-NEXT: int aa[10]; +// CHECK-NEXT: auto &raa = aa; +// CHECK-NEXT: #pragma omp target parallel for is_device_ptr(k) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: foo(); +// CHECK-NEXT: #pragma omp target parallel for is_device_ptr(z) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: foo(); +// CHECK-NEXT: #pragma omp target parallel for is_device_ptr(aa) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: foo(); +// CHECK-NEXT: #pragma omp target parallel for is_device_ptr(raa) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: foo(); +// CHECK-NEXT: #pragma omp target parallel for is_device_ptr(h) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: foo(); +// CHECK-NEXT: #pragma omp target parallel for is_device_ptr(rh) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: foo(); +// CHECK-NEXT: #pragma omp target parallel for is_device_ptr(da) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: foo(); + +// CHECK: template<> int *tmain<int *>(int *argc) { +// CHECK-NEXT: int *const da[5] = {0}; +// CHECK-NEXT: S6 h[10]; +// CHECK-NEXT: auto &rh = h; +// CHECK-NEXT: int *i; +// CHECK-NEXT: int *&j = i; +// CHECK-NEXT: int **k = &j; +// CHECK-NEXT: int **&z = k; +// CHECK-NEXT: int *aa[10]; +// CHECK-NEXT: auto &raa = aa; +// CHECK-NEXT: #pragma omp target parallel for is_device_ptr(k) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: foo(); +// CHECK-NEXT: #pragma omp target parallel for is_device_ptr(z) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: foo(); +// CHECK-NEXT: #pragma omp target parallel for is_device_ptr(aa) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: foo(); +// CHECK-NEXT: #pragma omp target parallel for is_device_ptr(raa) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: foo(); +// CHECK-NEXT: #pragma omp target parallel for is_device_ptr(h) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: foo(); +// CHECK-NEXT: #pragma omp target parallel for is_device_ptr(rh) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: foo(); +// CHECK-NEXT: #pragma omp target parallel for is_device_ptr(da) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: foo(); + +// CHECK-LABEL: int main(int argc, char **argv) { +int main(int argc, char **argv) { + const int da[5] = { 0 }; + S6 h[10]; + auto &rh = h; + int i; + int &j = i; + int *k = &j; + int *&z = k; + int aa[10]; + auto &raa = aa; +// CHECK-NEXT: const int da[5] = {0}; +// CHECK-NEXT: S6 h[10]; +// CHECK-NEXT: auto &rh = h; +// CHECK-NEXT: int i; +// CHECK-NEXT: int &j = i; +// CHECK-NEXT: int *k = &j; +// CHECK-NEXT: int *&z = k; +// CHECK-NEXT: int aa[10]; +// CHECK-NEXT: auto &raa = aa; +#pragma omp target parallel for is_device_ptr(k) + for (int i=0; i<100; i++) foo(); +// CHECK-NEXT: #pragma omp target parallel for is_device_ptr(k) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: foo(); + +#pragma omp target parallel for is_device_ptr(z) + for (int i=0; i<100; i++) foo(); +// CHECK-NEXT: #pragma omp target parallel for is_device_ptr(z) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: foo(); + +#pragma omp target parallel for is_device_ptr(aa) + for (int i=0; i<100; i++) foo(); +// CHECK-NEXT: #pragma omp target parallel for is_device_ptr(aa) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: foo(); + +#pragma omp target parallel for is_device_ptr(raa) + for (int i=0; i<100; i++) foo(); +// CHECK-NEXT: #pragma omp target parallel for is_device_ptr(raa) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: foo(); + +#pragma omp target parallel for is_device_ptr(h) + for (int i=0; i<100; i++) foo(); +// CHECK-NEXT: #pragma omp target parallel for is_device_ptr(h) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: foo(); + +#pragma omp target parallel for is_device_ptr(rh) + for (int i=0; i<100; i++) foo(); +// CHECK-NEXT: #pragma omp target parallel for is_device_ptr(rh) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: foo(); + +#pragma omp target parallel for is_device_ptr(da) + for (int i=0; i<100; i++) foo(); +// CHECK-NEXT: #pragma omp target parallel for is_device_ptr(da) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: foo(); + return tmain<int>(argc) + *tmain<int *>(&argc); +} + + +#endif diff --git a/test/OpenMP/target_parallel_for_is_device_ptr_messages.cpp b/test/OpenMP/target_parallel_for_is_device_ptr_messages.cpp new file mode 100644 index 000000000000..b3b33bf91ed0 --- /dev/null +++ b/test/OpenMP/target_parallel_for_is_device_ptr_messages.cpp @@ -0,0 +1,311 @@ +// RUN: %clang_cc1 -std=c++11 -verify -fopenmp %s + +struct ST { + int *a; +}; +typedef int arr[10]; +typedef ST STarr[10]; +typedef struct { + int a; +} S; +struct SA { + const int d = 5; + const int da[5] = { 0 }; + ST e; + ST g[10]; + STarr &rg = g; + int i; + int &j = i; + int *k = &j; + int *&z = k; + int aa[10]; + arr &raa = aa; + S *ps; + void func(int arg) { +#pragma omp target parallel for is_device_ptr // expected-error {{expected '(' after 'is_device_ptr'}} + for (int ii=0; ii<10; ii++) + ; +#pragma omp target parallel for is_device_ptr( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}} + for (int ii=0; ii<10; ii++) + ; +#pragma omp target parallel for is_device_ptr() // expected-error {{expected expression}} + for (int ii=0; ii<10; ii++) + ; +#pragma omp target parallel for is_device_ptr(alloc) // expected-error {{use of undeclared identifier 'alloc'}} + for (int ii=0; ii<10; ii++) + ; +#pragma omp target parallel for is_device_ptr(arg // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int ii=0; ii<10; ii++) + ; +#pragma omp target parallel for is_device_ptr(i) // expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int ii=0; ii<10; ii++) + ; +#pragma omp target parallel for is_device_ptr(j) // expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int ii=0; ii<10; ii++) + ; +#pragma omp target parallel for is_device_ptr(k) // OK + for (int ii=0; ii<10; ii++) + ; +#pragma omp target parallel for is_device_ptr(z) // OK + for (int ii=0; ii<10; ii++) + ; +#pragma omp target parallel for is_device_ptr(aa) // OK + for (int ii=0; ii<10; ii++) + ; +#pragma omp target parallel for is_device_ptr(raa) // OK + for (int ii=0; ii<10; ii++) + ; +#pragma omp target parallel for is_device_ptr(e) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int ii=0; ii<10; ii++) + ; +#pragma omp target parallel for is_device_ptr(g) // OK + for (int ii=0; ii<10; ii++) + ; +#pragma omp target parallel for is_device_ptr(rg) // OK + for (int ii=0; ii<10; ii++) + ; +#pragma omp target parallel for is_device_ptr(k,i,j) // expected-error2 {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int ii=0; ii<10; ii++) + ; +#pragma omp target parallel for is_device_ptr(d) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int ii=0; ii<10; ii++) + ; +#pragma omp target parallel for is_device_ptr(da) // OK + for (int ii=0; ii<10; ii++) + ; +#pragma omp target parallel for map(ps) is_device_ptr(ps) // expected-error{{variable already marked as mapped in current construct}} expected-note{{used here}} + for (int ii=0; ii<10; ii++) + ; +#pragma omp target parallel for is_device_ptr(ps) map(ps) // expected-error{{variable already marked as mapped in current construct}} expected-note{{used here}} + for (int ii=0; ii<10; ii++) + ; +#pragma omp target parallel for map(ps->a) is_device_ptr(ps) // expected-error{{variable already marked as mapped in current construct}} expected-note{{used here}} + for (int ii=0; ii<10; ii++) + ; +#pragma omp target parallel for is_device_ptr(ps) map(ps->a) // expected-error{{pointer cannot be mapped along with a section derived from itself}} expected-note{{used here}} + for (int ii=0; ii<10; ii++) + ; +#pragma omp target parallel for firstprivate(ps) is_device_ptr(ps) // expected-error{{firstprivate variable cannot be in a is_device_ptr clause in '#pragma omp target parallel for' directive}} expected-note{{defined as firstprivate}} + for (int ii=0; ii<10; ii++) + ; +#pragma omp target parallel for private(ps) is_device_ptr(ps) // expected-error{{private variable cannot be in a is_device_ptr clause in '#pragma omp target parallel for' directive}} expected-note{{defined as private}} + for (int ii=0; ii<10; ii++) + ; + + return; + } +}; +struct SB { + unsigned A; + unsigned B; + float Arr[100]; + float *Ptr; + float *foo() { + return &Arr[0]; + } +}; + +struct SC { + unsigned A : 2; + unsigned B : 3; + unsigned C; + unsigned D; + float Arr[100]; + SB S; + SB ArrS[100]; + SB *PtrS; + SB *&RPtrS; + float *Ptr; + + SC(SB *&_RPtrS) : RPtrS(_RPtrS) {} +}; + +union SD { + unsigned A; + float B; +}; + +struct S1; +extern S1 a; +class S2 { + mutable int a; +public: + S2():a(0) { } + S2(S2 &s2):a(s2.a) { } + static float S2s; + static const float S2sc; +}; +const float S2::S2sc = 0; +const S2 b; +const S2 ba[5]; +class S3 { + int a; +public: + S3():a(0) { } + S3(S3 &s3):a(s3.a) { } +}; +const S3 c; +const S3 ca[5]; +extern const int f; +class S4 { + int a; + S4(); + S4(const S4 &s4); +public: + S4(int v):a(v) { } +}; +class S5 { + int a; + S5():a(0) {} + S5(const S5 &s5):a(s5.a) { } +public: + S5(int v):a(v) { } +}; + +S3 h; +#pragma omp threadprivate(h) + +typedef struct { + int a; +} S6; + +template <typename T, int I> +T tmain(T argc) { + const T d = 5; + const T da[5] = { 0 }; + S4 e(4); + S5 g(5); + S6 h[10]; + auto &rh = h; + T i; + T &j = i; + T *k = &j; + T *&z = k; + T aa[10]; + auto &raa = aa; +#pragma omp target parallel for is_device_ptr // expected-error {{expected '(' after 'is_device_ptr'}} + for (int kk=0; kk<20; kk++) + ; +#pragma omp target parallel for is_device_ptr( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}} + for (int kk=0; kk<20; kk++) + ; +#pragma omp target parallel for is_device_ptr() // expected-error {{expected expression}} + for (int kk=0; kk<20; kk++) + ; +#pragma omp target parallel for is_device_ptr(alloc) // expected-error {{use of undeclared identifier 'alloc'}} + for (int kk=0; kk<20; kk++) + ; +#pragma omp target parallel for is_device_ptr(argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int kk=0; kk<20; kk++) + ; +#pragma omp target parallel for is_device_ptr(i) // expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int kk=0; kk<20; kk++) + ; +#pragma omp target parallel for is_device_ptr(j) // expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int kk=0; kk<20; kk++) + ; +#pragma omp target parallel for is_device_ptr(k) // OK + for (int kk=0; kk<20; kk++) + ; +#pragma omp target parallel for is_device_ptr(z) // OK + for (int kk=0; kk<20; kk++) + ; +#pragma omp target parallel for is_device_ptr(aa) // OK + for (int kk=0; kk<20; kk++) + ; +#pragma omp target parallel for is_device_ptr(raa) // OK + for (int kk=0; kk<20; kk++) + ; +#pragma omp target parallel for is_device_ptr(e) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int kk=0; kk<20; kk++) + ; +#pragma omp target parallel for is_device_ptr(g) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int kk=0; kk<20; kk++) + ; +#pragma omp target parallel for is_device_ptr(h) // OK + for (int kk=0; kk<20; kk++) + ; +#pragma omp target parallel for is_device_ptr(rh) // OK + for (int kk=0; kk<20; kk++) + ; +#pragma omp target parallel for is_device_ptr(k,i,j) // expected-error2 {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int kk=0; kk<20; kk++) + ; +#pragma omp target parallel for is_device_ptr(d) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int kk=0; kk<20; kk++) + ; +#pragma omp target parallel for is_device_ptr(da) // OK + for (int kk=0; kk<20; kk++) + ; + return 0; +} + +int main(int argc, char **argv) { + const int d = 5; + const int da[5] = { 0 }; + S4 e(4); + S5 g(5); + S6 h[10]; + auto &rh = h; + int i; + int &j = i; + int *k = &j; + int *&z = k; + int aa[10]; + auto &raa = aa; +#pragma omp target parallel for is_device_ptr // expected-error {{expected '(' after 'is_device_ptr'}} + for (int kk=0; kk<20; kk++) + ; +#pragma omp target parallel for is_device_ptr( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}} + for (int kk=0; kk<20; kk++) + ; +#pragma omp target parallel for is_device_ptr() // expected-error {{expected expression}} + for (int kk=0; kk<20; kk++) + ; +#pragma omp target parallel for is_device_ptr(alloc) // expected-error {{use of undeclared identifier 'alloc'}} + for (int kk=0; kk<20; kk++) + ; +#pragma omp target parallel for is_device_ptr(argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int kk=0; kk<20; kk++) + ; +#pragma omp target parallel for is_device_ptr(i) // expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int kk=0; kk<20; kk++) + ; +#pragma omp target parallel for is_device_ptr(j) // expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int kk=0; kk<20; kk++) + ; +#pragma omp target parallel for is_device_ptr(k) // OK + for (int kk=0; kk<20; kk++) + ; +#pragma omp target parallel for is_device_ptr(z) // OK + for (int kk=0; kk<20; kk++) + ; +#pragma omp target parallel for is_device_ptr(aa) // OK + for (int kk=0; kk<20; kk++) + ; +#pragma omp target parallel for is_device_ptr(raa) // OK + for (int kk=0; kk<20; kk++) + ; +#pragma omp target parallel for is_device_ptr(e) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int kk=0; kk<20; kk++) + ; +#pragma omp target parallel for is_device_ptr(g) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int kk=0; kk<20; kk++) + ; +#pragma omp target parallel for is_device_ptr(h) // OK + for (int kk=0; kk<20; kk++) + ; +#pragma omp target parallel for is_device_ptr(rh) // OK + for (int kk=0; kk<20; kk++) + ; +#pragma omp target parallel for is_device_ptr(k,i,j) // expected-error2 {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int kk=0; kk<20; kk++) + ; +#pragma omp target parallel for is_device_ptr(d) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int kk=0; kk<20; kk++) + ; +#pragma omp target parallel for is_device_ptr(da) // OK + for (int kk=0; kk<20; kk++) + ; + return tmain<int, 3>(argc); // expected-note {{in instantiation of function template specialization 'tmain<int, 3>' requested here}} +} diff --git a/test/OpenMP/target_parallel_for_simd_is_device_ptr_ast_print.cpp b/test/OpenMP/target_parallel_for_simd_is_device_ptr_ast_print.cpp new file mode 100644 index 000000000000..af98f99ada95 --- /dev/null +++ b/test/OpenMP/target_parallel_for_simd_is_device_ptr_ast_print.cpp @@ -0,0 +1,318 @@ +// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ast-print %s | FileCheck %s +// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s +// expected-no-diagnostics + +#ifndef HEADER +#define HEADER +struct ST { + int *a; +}; +typedef int arr[10]; +typedef ST STarr[10]; +struct SA { + const int da[5] = { 0 }; + ST g[10]; + STarr &rg = g; + int i; + int &j = i; + int *k = &j; + int *&z = k; + int aa[10]; + arr &raa = aa; + void func(int arg) { +#pragma omp target parallel for simd is_device_ptr(k) + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(z) + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(aa) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(raa) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(g) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(rg) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(da) // OK + for (int i=0; i<100; i++) + ; + return; + } +}; +// CHECK: struct SA +// CHECK-NEXT: const int da[5] = {0}; +// CHECK-NEXT: ST g[10]; +// CHECK-NEXT: STarr &rg = this->g; +// CHECK-NEXT: int i; +// CHECK-NEXT: int &j = this->i; +// CHECK-NEXT: int *k = &this->j; +// CHECK-NEXT: int *&z = this->k; +// CHECK-NEXT: int aa[10]; +// CHECK-NEXT: arr &raa = this->aa; +// CHECK-NEXT: func( +// CHECK-NEXT: #pragma omp target parallel for simd is_device_ptr(this->k) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +// CHECK-NEXT: #pragma omp target parallel for simd is_device_ptr(this->z) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +// CHECK-NEXT: #pragma omp target parallel for simd is_device_ptr(this->aa) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +// CHECK-NEXT: #pragma omp target parallel for simd is_device_ptr(this->raa) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +// CHECK-NEXT: #pragma omp target parallel for simd is_device_ptr(this->g) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +// CHECK-NEXT: #pragma omp target parallel for simd is_device_ptr(this->rg) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +// CHECK-NEXT: #pragma omp target parallel for simd is_device_ptr(this->da) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; + +struct SB { + unsigned A; + unsigned B; + float Arr[100]; + float *Ptr; + float *foo() { + return &Arr[0]; + } +}; + +struct SC { + unsigned A : 2; + unsigned B : 3; + unsigned C; + unsigned D; + float Arr[100]; + SB S; + SB ArrS[100]; + SB *PtrS; + SB *&RPtrS; + float *Ptr; + + SC(SB *&_RPtrS) : RPtrS(_RPtrS) {} +}; + +union SD { + unsigned A; + float B; +}; + +struct S1; +extern S1 a; +class S2 { + mutable int a; +public: + S2():a(0) { } + S2(S2 &s2):a(s2.a) { } + static float S2s; + static const float S2sc; +}; +const float S2::S2sc = 0; +const S2 b; +const S2 ba[5]; +class S3 { + int a; +public: + S3():a(0) { } + S3(S3 &s3):a(s3.a) { } +}; +const S3 c; +const S3 ca[5]; +extern const int f; +class S4 { + int a; + S4(); + S4(const S4 &s4); +public: + S4(int v):a(v) { } +}; +class S5 { + int a; + S5():a(0) {} + S5(const S5 &s5):a(s5.a) { } +public: + S5(int v):a(v) { } +}; + +S3 h; +#pragma omp threadprivate(h) + +typedef struct { + int a; +} S6; + +template <typename T> +T tmain(T argc) { + const T da[5] = { 0 }; + S6 h[10]; + auto &rh = h; + T i; + T &j = i; + T *k = &j; + T *&z = k; + T aa[10]; + auto &raa = aa; +#pragma omp target parallel for simd is_device_ptr(k) + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(z) + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(aa) + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(raa) + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(h) + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(rh) + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(da) + for (int i=0; i<100; i++) + ; + return 0; +} + +// CHECK: template<> int tmain<int>(int argc) { +// CHECK-NEXT: const int da[5] = {0}; +// CHECK-NEXT: S6 h[10]; +// CHECK-NEXT: auto &rh = h; +// CHECK-NEXT: int i; +// CHECK-NEXT: int &j = i; +// CHECK-NEXT: int *k = &j; +// CHECK-NEXT: int *&z = k; +// CHECK-NEXT: int aa[10]; +// CHECK-NEXT: auto &raa = aa; +// CHECK-NEXT: #pragma omp target parallel for simd is_device_ptr(k) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +// CHECK-NEXT: #pragma omp target parallel for simd is_device_ptr(z) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +// CHECK-NEXT: #pragma omp target parallel for simd is_device_ptr(aa) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +// CHECK-NEXT: #pragma omp target parallel for simd is_device_ptr(raa) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +// CHECK-NEXT: #pragma omp target parallel for simd is_device_ptr(h) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +// CHECK-NEXT: #pragma omp target parallel for simd is_device_ptr(rh) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +// CHECK-NEXT: #pragma omp target parallel for simd is_device_ptr(da) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; + +// CHECK: template<> int *tmain<int *>(int *argc) { +// CHECK-NEXT: int *const da[5] = {0}; +// CHECK-NEXT: S6 h[10]; +// CHECK-NEXT: auto &rh = h; +// CHECK-NEXT: int *i; +// CHECK-NEXT: int *&j = i; +// CHECK-NEXT: int **k = &j; +// CHECK-NEXT: int **&z = k; +// CHECK-NEXT: int *aa[10]; +// CHECK-NEXT: auto &raa = aa; +// CHECK-NEXT: #pragma omp target parallel for simd is_device_ptr(k) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +// CHECK-NEXT: #pragma omp target parallel for simd is_device_ptr(z) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +// CHECK-NEXT: #pragma omp target parallel for simd is_device_ptr(aa) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +// CHECK-NEXT: #pragma omp target parallel for simd is_device_ptr(raa) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +// CHECK-NEXT: #pragma omp target parallel for simd is_device_ptr(h) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +// CHECK-NEXT: #pragma omp target parallel for simd is_device_ptr(rh) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +// CHECK-NEXT: #pragma omp target parallel for simd is_device_ptr(da) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; + +// CHECK-LABEL: int main(int argc, char **argv) { +int main(int argc, char **argv) { + const int da[5] = { 0 }; + S6 h[10]; + auto &rh = h; + int i; + int &j = i; + int *k = &j; + int *&z = k; + int aa[10]; + auto &raa = aa; +// CHECK-NEXT: const int da[5] = {0}; +// CHECK-NEXT: S6 h[10]; +// CHECK-NEXT: auto &rh = h; +// CHECK-NEXT: int i; +// CHECK-NEXT: int &j = i; +// CHECK-NEXT: int *k = &j; +// CHECK-NEXT: int *&z = k; +// CHECK-NEXT: int aa[10]; +// CHECK-NEXT: auto &raa = aa; +#pragma omp target parallel for simd is_device_ptr(k) +// CHECK-NEXT: #pragma omp target parallel for simd is_device_ptr(k) + for (int i=0; i<100; i++) + ; +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +#pragma omp target parallel for simd is_device_ptr(z) +// CHECK-NEXT: #pragma omp target parallel for simd is_device_ptr(z) + for (int i=0; i<100; i++) + ; +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +#pragma omp target parallel for simd is_device_ptr(aa) +// CHECK-NEXT: #pragma omp target parallel for simd is_device_ptr(aa) + for (int i=0; i<100; i++) + ; +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +#pragma omp target parallel for simd is_device_ptr(raa) +// CHECK-NEXT: #pragma omp target parallel for simd is_device_ptr(raa) + for (int i=0; i<100; i++) + ; +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +#pragma omp target parallel for simd is_device_ptr(h) +// CHECK-NEXT: #pragma omp target parallel for simd is_device_ptr(h) + for (int i=0; i<100; i++) + ; +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +#pragma omp target parallel for simd is_device_ptr(rh) +// CHECK-NEXT: #pragma omp target parallel for simd is_device_ptr(rh) + for (int i=0; i<100; i++) + ; +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +#pragma omp target parallel for simd is_device_ptr(da) +// CHECK-NEXT: #pragma omp target parallel for simd is_device_ptr(da) + for (int i=0; i<100; i++) + ; +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; + return tmain<int>(argc) + *tmain<int *>(&argc); +} +#endif diff --git a/test/OpenMP/target_parallel_for_simd_is_device_ptr_messages.cpp b/test/OpenMP/target_parallel_for_simd_is_device_ptr_messages.cpp new file mode 100644 index 000000000000..435b9a95e9e6 --- /dev/null +++ b/test/OpenMP/target_parallel_for_simd_is_device_ptr_messages.cpp @@ -0,0 +1,337 @@ +// RUN: %clang_cc1 -std=c++11 -verify -fopenmp %s +struct ST { + int *a; +}; +typedef int arr[10]; +typedef ST STarr[10]; +struct SA { + const int d = 5; + const int da[5] = { 0 }; + ST e; + ST g[10]; + STarr &rg = g; + int i; + int &j = i; + int *k = &j; + int *&z = k; + int aa[10]; + arr &raa = aa; + void func(int arg) { +#pragma omp target parallel for simd is_device_ptr // expected-error {{expected '(' after 'is_device_ptr'}} + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}} + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr() // expected-error {{expected expression}} + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(alloc) // expected-error {{use of undeclared identifier 'alloc'}} + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(arg // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(i) // expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(j) // expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(k) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(z) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(aa) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(raa) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(e) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(g) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(rg) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(k,i,j) // expected-error2 {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(d) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(da) // OK + for (int i=0; i<100; i++) + ; + return; + } +}; +struct SB { + unsigned A; + unsigned B; + float Arr[100]; + float *Ptr; + float *foo() { + return &Arr[0]; + } +}; + +struct SC { + unsigned A : 2; + unsigned B : 3; + unsigned C; + unsigned D; + float Arr[100]; + SB S; + SB ArrS[100]; + SB *PtrS; + SB *&RPtrS; + float *Ptr; + + SC(SB *&_RPtrS) : RPtrS(_RPtrS) {} +}; + +union SD { + unsigned A; + float B; +}; + +struct S1; +extern S1 a; +class S2 { + mutable int a; +public: + S2():a(0) { } + S2(S2 &s2):a(s2.a) { } + static float S2s; + static const float S2sc; +}; +const float S2::S2sc = 0; +const S2 b; +const S2 ba[5]; +class S3 { + int a; +public: + S3():a(0) { } + S3(S3 &s3):a(s3.a) { } +}; +const S3 c; +const S3 ca[5]; +extern const int f; +class S4 { + int a; + S4(); + S4(const S4 &s4); +public: + S4(int v):a(v) { } +}; +class S5 { + int a; + S5():a(0) {} + S5(const S5 &s5):a(s5.a) { } +public: + S5(int v):a(v) { } +}; + +S3 h; +#pragma omp threadprivate(h) + +typedef struct { + int a; +} S6; + +template <typename T, int I> +T tmain(T argc) { + const T d = 5; + const T da[5] = { 0 }; + S4 e(4); + S5 g(5); + S6 h[10]; + auto &rh = h; + T i; + T &j = i; + T *k = &j; + T *&z = k; + T aa[10]; + auto &raa = aa; + S6 *ps; +#pragma omp target parallel for simd is_device_ptr // expected-error {{expected '(' after 'is_device_ptr'}} + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}} + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr() // expected-error {{expected expression}} + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(alloc) // expected-error {{use of undeclared identifier 'alloc'}} + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(i) // expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(j) // expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(k) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(z) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(aa) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(raa) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(e) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(g) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(h) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(rh) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(k,i,j) // expected-error2 {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(d) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(da) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd map(ps) is_device_ptr(ps) // expected-error{{variable already marked as mapped in current construct}} expected-note{{used here}} + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(ps) map(ps) // expected-error{{variable already marked as mapped in current construct}} expected-note{{used here}} + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd map(ps->a) is_device_ptr(ps) // expected-error{{variable already marked as mapped in current construct}} expected-note{{used here}} + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(ps) map(ps->a) // expected-error{{pointer cannot be mapped along with a section derived from itself}} expected-note{{used here}} + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(ps) firstprivate(ps) // expected-error{{firstprivate variable cannot be in a is_device_ptr clause in '#pragma omp target parallel for simd' directive}} + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd firstprivate(ps) is_device_ptr(ps) // expected-error{{firstprivate variable cannot be in a is_device_ptr clause in '#pragma omp target parallel for simd' directive}} expected-note{{defined as firstprivate}} + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(ps) private(ps) // expected-error{{private variable cannot be in a is_device_ptr clause in '#pragma omp target parallel for simd' directive}} + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd private(ps) is_device_ptr(ps) // expected-error{{private variable cannot be in a is_device_ptr clause in '#pragma omp target parallel for simd' directive}} expected-note{{defined as private}} + for (int i=0; i<100; i++) + ; + return 0; +} + +int main(int argc, char **argv) { + const int d = 5; + const int da[5] = { 0 }; + S4 e(4); + S5 g(5); + S6 h[10]; + auto &rh = h; + int i; + int &j = i; + int *k = &j; + int *&z = k; + int aa[10]; + auto &raa = aa; + S6 *ps; +#pragma omp target parallel for simd is_device_ptr // expected-error {{expected '(' after 'is_device_ptr'}} + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}} + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr() // expected-error {{expected expression}} + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(alloc) // expected-error {{use of undeclared identifier 'alloc'}} + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(i) // expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(j) // expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(k) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(z) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(aa) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(raa) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(e) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(g) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(h) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(rh) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(k,i,j) // expected-error2 {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(d) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(da) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd map(ps) is_device_ptr(ps) // expected-error{{variable already marked as mapped in current construct}} expected-note{{used here}} + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(ps) map(ps) // expected-error{{variable already marked as mapped in current construct}} expected-note{{used here}} + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd map(ps->a) is_device_ptr(ps) // expected-error{{variable already marked as mapped in current construct}} expected-note{{used here}} + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(ps) map(ps->a) // expected-error{{pointer cannot be mapped along with a section derived from itself}} expected-note{{used here}} + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(ps) firstprivate(ps) // expected-error{{firstprivate variable cannot be in a is_device_ptr clause in '#pragma omp target parallel for simd' directive}} + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd firstprivate(ps) is_device_ptr(ps) // expected-error{{firstprivate variable cannot be in a is_device_ptr clause in '#pragma omp target parallel for simd' directive}} expected-note{{defined as firstprivate}} + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd is_device_ptr(ps) private(ps) // expected-error{{private variable cannot be in a is_device_ptr clause in '#pragma omp target parallel for simd' directive}} + for (int i=0; i<100; i++) + ; +#pragma omp target parallel for simd private(ps) is_device_ptr(ps) // expected-error{{private variable cannot be in a is_device_ptr clause in '#pragma omp target parallel for simd' directive}} expected-note{{defined as private}} + for (int i=0; i<100; i++) + ; + return tmain<int, 3>(argc); // expected-note {{in instantiation of function template specialization 'tmain<int, 3>' requested here}} +} diff --git a/test/OpenMP/target_teams_distribute_collapse_messages.cpp b/test/OpenMP/target_teams_distribute_collapse_messages.cpp index f646655a09e1..4bc4a7b79ccf 100644 --- a/test/OpenMP/target_teams_distribute_collapse_messages.cpp +++ b/test/OpenMP/target_teams_distribute_collapse_messages.cpp @@ -1,8 +1,13 @@ // RUN: %clang_cc1 -verify -fopenmp %s +// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s +// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s void foo() { } +#if __cplusplus >= 201103L +// expected-note@+2 4 {{declared here}} +#endif bool foobool(int argc) { return argc; } @@ -43,6 +48,9 @@ T tmain(T argc, S **argv) { //expected-note 2 {{declared here}} for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST]; // expected-error 2 {{expected 2 for loops after '#pragma omp target teams distribute', but found only 1}} +#if __cplusplus >= 201103L +// expected-note@+5 2 {{non-constexpr function 'foobool' cannot be used in a constant expression}} +#endif // expected-error@+3 2 {{directive '#pragma omp target teams distribute' cannot contain more than one 'collapse' clause}} // expected-error@+2 2 {{argument to 'collapse' clause must be a strictly positive integer value}} // expected-error@+1 2 {{expression is not an integral constant expression}} @@ -54,7 +62,11 @@ T tmain(T argc, S **argv) { //expected-note 2 {{declared here}} for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST]; -// expected-error@+1 2 {{expression is not an integral constant expression}} +#if __cplusplus <= 199711L + // expected-error@+4 2 {{expression is not an integral constant expression}} +#else + // expected-error@+2 2 {{integral constant expression must have integral or unscoped enumeration type, not 'char *'}} +#endif #pragma omp target teams distribute collapse (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST]; @@ -93,10 +105,17 @@ int main(int argc, char **argv) { for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4]; // expected-error {{expected 4 for loops after '#pragma omp target teams distribute', but found only 1}} -#pragma omp target teams distribute collapse (foobool(1) > 0 ? 1 : 2) // expected-error {{expression is not an integral constant expression}} +// expected-error@+4 {{expression is not an integral constant expression}} +#if __cplusplus >= 201103L +// expected-note@+2 {{non-constexpr function 'foobool' cannot be used in a constant expression}} +#endif +#pragma omp target teams distribute collapse (foobool(1) > 0 ? 1 : 2) for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4]; +#if __cplusplus >= 201103L + // expected-note@+5{{non-constexpr function 'foobool' cannot be used in a constant expression}} +#endif // expected-error@+3 {{expression is not an integral constant expression}} // expected-error@+2 2 {{directive '#pragma omp target teams distribute' cannot contain more than one 'collapse' clause}} // expected-error@+1 2 {{argument to 'collapse' clause must be a strictly positive integer value}} @@ -108,7 +127,11 @@ int main(int argc, char **argv) { for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4]; -// expected-error@+1 {{expression is not an integral constant expression}} +#if __cplusplus <= 199711L + // expected-error@+4 {{expression is not an integral constant expression}} +#else + // expected-error@+2 {{integral constant expression must have integral or unscoped enumeration type, not 'char *'}} +#endif #pragma omp target teams distribute collapse (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4]; diff --git a/test/OpenMP/target_teams_distribute_simd_aligned_messages.cpp b/test/OpenMP/target_teams_distribute_simd_aligned_messages.cpp new file mode 100644 index 000000000000..e9df563ded2c --- /dev/null +++ b/test/OpenMP/target_teams_distribute_simd_aligned_messages.cpp @@ -0,0 +1,231 @@ +// RUN: %clang_cc1 -x c++ -std=c++11 -verify -fopenmp %s + +struct B { + static int ib[20]; // expected-note 0 {{'B::ib' declared here}} + static constexpr int bfoo() { return 8; } +}; +namespace X { + B x; // expected-note {{'x' defined here}} +}; +constexpr int bfoo() { return 4; } + +int **z; +const int C1 = 1; +const int C2 = 2; +void test_aligned_colons(int *&rp) +{ + int *B = 0; + +#pragma omp target teams distribute simd aligned(B:bfoo()) + for (int i = 0; i < 10; ++i) ; + +#pragma omp target teams distribute simd aligned(B::ib:B:bfoo()) // expected-error {{unexpected ':' in nested name specifier; did you mean '::'}} + for (int i = 0; i < 10; ++i) ; + +#pragma omp target teams distribute simd aligned(B:B::bfoo()) + for (int i = 0; i < 10; ++i) ; + +#pragma omp target teams distribute simd aligned(z:B:bfoo()) // expected-error {{unexpected ':' in nested name specifier; did you mean '::'?}} + for (int i = 0; i < 10; ++i) ; + +#pragma omp target teams distribute simd aligned(B:B::bfoo()) + for (int i = 0; i < 10; ++i) ; + +#pragma omp target teams distribute simd aligned(X::x : ::z) // expected-error {{integral constant expression must have integral or unscoped enumeration type, not 'int **'}} expected-error {{argument of aligned clause should be array, pointer, reference to array or reference to pointer, not 'B'}} + for (int i = 0; i < 10; ++i) ; + +#pragma omp target teams distribute simd aligned(B,rp,::z: X::x) // expected-error {{integral constant expression must have integral or unscoped enumeration type, not 'B'}} + for (int i = 0; i < 10; ++i) ; + +#pragma omp target teams distribute simd aligned(::z) + for (int i = 0; i < 10; ++i) ; + +#pragma omp target teams distribute simd aligned(B::bfoo()) // expected-error {{expected variable name}} + for (int i = 0; i < 10; ++i) ; + +#pragma omp target teams distribute simd aligned(B::ib,B:C1+C2) // expected-warning {{aligned clause will be ignored because the requested alignment is not a power of 2}} + for (int i = 0; i < 10; ++i) ; +} + +// expected-note@+1 {{'num' defined here}} +template<int L, class T, class N> T test_template(T* arr, N num) { + N i; + T sum = (T)0; + T ind2 = - num * L; + // Negative number is passed as L. + +#pragma omp target teams distribute simd aligned(arr:L) // expected-error {{argument to 'aligned' clause must be a strictly positive integer value}} + for (i = 0; i < num; ++i) { + T cur = arr[(int)ind2]; + ind2 += L; + sum += cur; + } + +#pragma omp target teams distribute simd aligned(num:4) // expected-error {{argument of aligned clause should be array, pointer, reference to array or reference to pointer, not 'int'}} + for (i = 0; i < num; ++i); + + return T(); +} + +template<int LEN> int test_warn() { + int *ind2 = 0; +#pragma omp target teams distribute simd aligned(ind2:LEN) // expected-error {{argument to 'aligned' clause must be a strictly positive integer value}} + for (int i = 0; i < 100; i++) { + ind2 += LEN; + } + return 0; +} + +struct S1; // expected-note 2 {{declared here}} +extern S1 a; // expected-note {{'a' declared here}} +class S2 { + mutable int a; +public: + S2():a(0) { } +}; +const S2 b; // expected-note 1 {{'b' defined here}} +const S2 ba[5]; +class S3 { + int a; +public: + S3():a(0) { } +}; +const S3 ca[5]; +class S4 { + int a; + S4(); +public: + S4(int v):a(v) { } +}; +class S5 { + int a; + S5():a(0) {} +public: + S5(int v):a(v) { } +}; + +S3 h; // expected-note 2 {{'h' defined here}} +#pragma omp threadprivate(h) + +template<class I, class C> int foomain(I argc, C **argv) { + I e(argc); + I g(argc); + int i; // expected-note {{declared here}} expected-note {{'i' defined here}} + // expected-note@+2 {{declared here}} + // expected-note@+1 {{reference to 'i' is not a constant expression}} + int &j = i; + +#pragma omp target teams distribute simd aligned // expected-error {{expected '(' after 'aligned'}} + for (I k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd aligned ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (I k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd aligned () // expected-error {{expected expression}} + for (I k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd aligned (argc // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (I k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd aligned (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (I k = 0; k < argc; ++k) ++k; + +// FIXME: Should argc really be a pointer? +#pragma omp target teams distribute simd aligned (*argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}} + for (I k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd aligned (argc : 5) // expected-warning {{aligned clause will be ignored because the requested alignment is not a power of 2}} + for (I k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd aligned (S1) // expected-error {{'S1' does not refer to a value}} + for (I k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd aligned (argv[1]) // expected-error {{expected variable name}} + for (I k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd aligned(e, g) + for (I k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd aligned(h) // expected-error {{argument of aligned clause should be array, pointer, reference to array or reference to pointer, not 'S3'}} + for (I k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd aligned(i) // expected-error {{argument of aligned clause should be array, pointer, reference to array or reference to pointer, not 'int'}} + for (I k = 0; k < argc; ++k) ++k; + + #pragma omp parallel + { + int *v = 0; + I i; + #pragma omp target teams distribute simd aligned(v:16) + for (I k = 0; k < argc; ++k) { i = k; v += 2; } + } + float *f; + +#pragma omp target teams distribute simd aligned(f) + for (I k = 0; k < argc; ++k) ++k; + + int v = 0; + +#pragma omp target teams distribute simd aligned(f:j) // expected-note {{initializer of 'j' is not a constant expression}} expected-error {{expression is not an integral constant expression}} + + for (I k = 0; k < argc; ++k) { ++k; v += j; } + +#pragma omp target teams distribute simd aligned(f) + for (I k = 0; k < argc; ++k) ++k; + + return 0; +} + +// expected-note@+1 2 {{'argc' defined here}} +int main(int argc, char **argv) { + double darr[100]; + // expected-note@+1 {{in instantiation of function template specialization 'test_template<-4, double, int>' requested here}} + test_template<-4>(darr, 4); + test_warn<4>(); // ok + // expected-note@+1 {{in instantiation of function template specialization 'test_warn<0>' requested here}} + test_warn<0>(); + + int i; + int &j = i; + +#pragma omp target teams distribute simd aligned // expected-error {{expected '(' after 'aligned'}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd aligned ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd aligned () // expected-error {{expected expression}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd aligned (argv // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd aligned (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{argument of aligned clause should be array, pointer, reference to array or reference to pointer, not 'int'}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams +#pragma omp distribute simd aligned (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams +#pragma omp distribute simd aligned (argc) // expected-error {{argument of aligned clause should be array, pointer, reference to array or reference to pointer, not 'int'}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd aligned (S1) // expected-error {{'S1' does not refer to a value}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd aligned (a, b) // expected-error {{argument of aligned clause should be array, pointer, reference to array or reference to pointer, not 'S1'}} expected-error {{argument of aligned clause should be array, pointer, reference to array or reference to pointer, not 'S2'}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd aligned (argv[1]) // expected-error {{expected variable name}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd aligned(h) // expected-error {{argument of aligned clause should be array, pointer, reference to array or reference to pointer, not 'S3'}} + for (int k = 0; k < argc; ++k) ++k; + + int *pargc = &argc; + // expected-note@+1 {{in instantiation of function template specialization 'foomain<int *, char>' requested here}} + foomain<int*,char>(pargc,argv); + return 0; +} + diff --git a/test/OpenMP/target_teams_distribute_simd_ast_print.cpp b/test/OpenMP/target_teams_distribute_simd_ast_print.cpp new file mode 100644 index 000000000000..77732ef56011 --- /dev/null +++ b/test/OpenMP/target_teams_distribute_simd_ast_print.cpp @@ -0,0 +1,198 @@ +// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s +// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s +// expected-no-diagnostics + +#ifndef HEADER +#define HEADER + +void foo() {} + +struct S { + S(): a(0) {} + S(int v) : a(v) {} + int a; + typedef int type; +}; + +template <typename T> +class S7 : public T { +protected: + T a; + S7() : a(0) {} + +public: + S7(typename T::type v) : a(v) { +#pragma omp target teams distribute simd private(a) private(this->a) private(T::a) + for (int k = 0; k < a.a; ++k) + ++this->a.a; + } + S7 &operator=(S7 &s) { +#pragma omp target teams distribute simd private(a) private(this->a) + for (int k = 0; k < s.a.a; ++k) + ++s.a.a; + return *this; + } + void foo() { + int b, argv, d, c, e, f; +#pragma omp target teams distribute simd private(b), firstprivate(argv) shared(d) reduction(+:c) reduction(max:e) num_teams(f) thread_limit(d) + for (int k = 0; k < a.a; ++k) + ++a.a; + } + void bar() { + int arr[10]; + const int alen = 16; + const int slen1 = 8; + const int slen2 = 8; +#pragma omp target teams distribute simd simdlen(slen1) safelen(slen2) aligned(arr:alen) + for (int k = 0; k < a.a; ++k) + ++a.a; + } +}; +// CHECK: #pragma omp target teams distribute simd private(this->a) private(this->a) private(T::a) +// CHECK: #pragma omp target teams distribute simd private(this->a) private(this->a) +// CHECK: #pragma omp target teams distribute simd private(b) firstprivate(argv) shared(d) reduction(+: c) reduction(max: e) num_teams(f) thread_limit(d) +// CHECK: #pragma omp target teams distribute simd simdlen(slen1) safelen(slen2) aligned(arr: alen) +// CHECK: #pragma omp target teams distribute simd private(this->a) private(this->a) private(this->S::a) + +class S8 : public S7<S> { + S8() {} + +public: + S8(int v) : S7<S>(v){ +#pragma omp target teams distribute simd private(a) private(this->a) private(S7<S>::a) + for (int k = 0; k < a.a; ++k) + ++this->a.a; + } + S8 &operator=(S8 &s) { +#pragma omp target teams distribute simd private(a) private(this->a) + for (int k = 0; k < s.a.a; ++k) + ++s.a.a; + return *this; + } + void bar() { + int b, argv, d, c, e, f; +#pragma omp target teams distribute simd private(b), firstprivate(argv) shared(d) reduction(+:c) reduction(max:e) num_teams(f) thread_limit(d) + for (int k = 0; k < a.a; ++k) + ++a.a; + } + void foo() { + const int alen = 16; + const int slen1 = 8; + const int slen2 = 8; + int arr[10]; +#pragma omp target teams distribute simd simdlen(slen1) safelen(slen2) aligned(arr:alen) + for (int k = 0; k < a.a; ++k) + ++a.a; + } +}; +// CHECK: #pragma omp target teams distribute simd private(this->a) private(this->a) private(this->S7<S>::a) +// CHECK: #pragma omp target teams distribute simd private(this->a) private(this->a) +// CHECK: #pragma omp target teams distribute simd private(b) firstprivate(argv) shared(d) reduction(+: c) reduction(max: e) num_teams(f) thread_limit(d) +// CHECK: #pragma omp target teams distribute simd simdlen(slen1) safelen(slen2) aligned(arr: alen) + +template <class T, int N> +T tmain(T argc) { + T b = argc, c, d, e, f, g; + static T a; +// CHECK: static T a; + const T clen = 5; + const T alen = 16; + int arr[10]; +#pragma omp target teams distribute simd + for (int i=0; i < 2; ++i) + a = 2; +// CHECK: #pragma omp target teams distribute simd +// CHECK-NEXT: for (int i = 0; i < 2; ++i) +// CHECK-NEXT: a = 2; +#pragma omp target teams distribute simd private(argc, b), firstprivate(c, d), collapse(2) + for (int i = 0; i < 10; ++i) + for (int j = 0; j < 10; ++j) + foo(); +// CHECK: #pragma omp target teams distribute simd private(argc,b) firstprivate(c,d) collapse(2) +// CHECK-NEXT: for (int i = 0; i < 10; ++i) +// CHECK-NEXT: for (int j = 0; j < 10; ++j) +// CHECK-NEXT: foo(); + for (int i = 0; i < 10; ++i) + foo(); +// CHECK: for (int i = 0; i < 10; ++i) +// CHECK-NEXT: foo(); +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) + foo(); +// CHECK: #pragma omp target teams distribute simd +// CHECK-NEXT: for (int i = 0; i < 10; ++i) +// CHECK-NEXT: foo(); +#pragma omp target teams distribute simd private(b), firstprivate(argc) shared(d) reduction(+:c) reduction(max:e) num_teams(f) thread_limit(d) + for (int k = 0; k < 10; ++k) + e += d + argc; +// CHECK: #pragma omp target teams distribute simd private(b) firstprivate(argc) shared(d) reduction(+: c) reduction(max: e) num_teams(f) thread_limit(d) +// CHECK-NEXT: for (int k = 0; k < 10; ++k) +// CHECK-NEXT: e += d + argc; +#pragma omp target teams distribute simd simdlen(clen-1) linear(d) + for (int k = 0; k < 10; ++k) + e += d + argc; +// CHECK: #pragma omp target teams distribute simd simdlen(clen - 1) linear(d) +// CHECK-NEXT: for (int k = 0; k < 10; ++k) +// CHECK-NEXT: e += d + argc; +#pragma omp target teams distribute simd safelen(clen-1) aligned(arr:alen) + for (int k = 0; k < 10; ++k) + e += d + argc + arr[k]; +// CHECK: #pragma omp target teams distribute simd safelen(clen - 1) aligned(arr: alen) +// CHECK-NEXT: for (int k = 0; k < 10; ++k) +// CHECK-NEXT: e += d + argc + arr[k]; + return T(); +} + +int main (int argc, char **argv) { + int b = argc, c, d, e, f, g; + static int a; +// CHECK: static int a; + const int clen = 5; + const int N = 10; + int arr[10]; +#pragma omp target teams distribute simd + for (int i=0; i < 2; ++i) + a = 2; +// CHECK: #pragma omp target teams distribute simd +// CHECK-NEXT: for (int i = 0; i < 2; ++i) +// CHECK-NEXT: a = 2; +#pragma omp target teams distribute simd private(argc,b),firstprivate(argv, c), collapse(2) + for (int i = 0; i < 10; ++i) + for (int j = 0; j < 10; ++j) + foo(); +// CHECK: #pragma omp target teams distribute simd private(argc,b) firstprivate(argv,c) collapse(2) +// CHECK-NEXT: for (int i = 0; i < 10; ++i) +// CHECK-NEXT: for (int j = 0; j < 10; ++j) +// CHECK-NEXT: foo(); + for (int i = 0; i < 10; ++i) + foo(); +// CHECK: for (int i = 0; i < 10; ++i) +// CHECK-NEXT: foo(); +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i)foo(); +// CHECK: #pragma omp target teams distribute simd +// CHECK-NEXT: for (int i = 0; i < 10; ++i) +// CHECK-NEXT: foo(); +#pragma omp target teams distribute simd private(b), firstprivate(argc) shared(d) reduction(+:c) reduction(max:e) num_teams(f) thread_limit(d) + for (int k = 0; k < 10; ++k) + e += d + argc; +// CHECK: #pragma omp target teams distribute simd private(b) firstprivate(argc) shared(d) reduction(+: c) reduction(max: e) num_teams(f) thread_limit(d) +// CHECK-NEXT: for (int k = 0; k < 10; ++k) +// CHECK-NEXT: e += d + argc; +#pragma omp target teams distribute simd simdlen(clen-1) linear(d) + for (int k = 0; k < 10; ++k) + e += d + argc; +// CHECK: #pragma omp target teams distribute simd simdlen(clen - 1) linear(d) +// CHECK-NEXT: for (int k = 0; k < 10; ++k) +// CHECK-NEXT: e += d + argc; +#pragma omp target teams distribute simd safelen(clen-1) aligned(arr:N+6) + for (int k = 0; k < 10; ++k) + e += d + argc + arr[k]; +// CHECK: #pragma omp target teams distribute simd safelen(clen - 1) aligned(arr: N + 6) +// CHECK-NEXT: for (int k = 0; k < 10; ++k) +// CHECK-NEXT: e += d + argc + arr[k]; + return (0); +} + +#endif diff --git a/test/OpenMP/target_teams_distribute_simd_collapse_messages.cpp b/test/OpenMP/target_teams_distribute_simd_collapse_messages.cpp new file mode 100644 index 000000000000..39937f90fb34 --- /dev/null +++ b/test/OpenMP/target_teams_distribute_simd_collapse_messages.cpp @@ -0,0 +1,149 @@ +// RUN: %clang_cc1 -verify -fopenmp %s +// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s +// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s + +void foo() { +} + +#if __cplusplus >= 201103L +// expected-note@+2 4 {{declared here}} +#endif +bool foobool(int argc) { + return argc; +} + +struct S1; // expected-note {{declared here}} + +template <class T, typename S, int N, int ST> // expected-note {{declared here}} +T tmain(T argc, S **argv) { //expected-note 2 {{declared here}} +#pragma omp target teams distribute simd collapse // expected-error {{expected '(' after 'collapse'}} + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i-ST]; + +#pragma omp target teams distribute simd collapse ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int i = ST; i < N; i++) + + argv[0][i] = argv[0][i] - argv[0][i-ST]; +#pragma omp target teams distribute simd collapse () // expected-error {{expected expression}} + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i-ST]; + +// expected-error@+3 {{expected ')'}} expected-note@+3 {{to match this '('}} +// expected-error@+2 2 {{expression is not an integral constant expression}} +// expected-note@+1 2 {{read of non-const variable 'argc' is not allowed in a constant expression}} +#pragma omp target teams distribute simd collapse (argc + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i-ST]; + +// expected-error@+1 2 {{argument to 'collapse' clause must be a strictly positive integer value}} +#pragma omp target teams distribute simd collapse (ST // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i-ST]; + +#pragma omp target teams distribute simd collapse (1)) // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute simd' are ignored}} + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i-ST]; + +#pragma omp target teams distribute simd collapse ((ST > 0) ? 1 + ST : 2) // expected-note 2 {{as specified in 'collapse' clause}} + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i-ST]; // expected-error 2 {{expected 2 for loops after '#pragma omp target teams distribute simd', but found only 1}} + +// expected-error@+6 2 {{directive '#pragma omp target teams distribute simd' cannot contain more than one 'collapse' clause}} +// expected-error@+5 2 {{argument to 'collapse' clause must be a strictly positive integer value}} +// expected-error@+4 2 {{expression is not an integral constant expression}} +#if __cplusplus >= 201103L +// expected-note@+2 2 {{non-constexpr function 'foobool' cannot be used in a constant expression}} +#endif +#pragma omp target teams distribute simd collapse (foobool(argc)), collapse (true), collapse (-5) + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i-ST]; + +#pragma omp distribute collapse (S) // expected-error {{'S' does not refer to a value}} + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i-ST]; + +#if __cplusplus <= 199711L + // expected-error@+4 2 {{expression is not an integral constant expression}} +#else + // expected-error@+2 2 {{integral constant expression must have integral or unscoped enumeration type, not 'char *'}} +#endif +#pragma omp target teams distribute simd collapse (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i-ST]; + +#pragma omp target teams distribute simd collapse (1) + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i-ST]; + +#pragma omp target teams distribute simd collapse (N) // expected-error {{argument to 'collapse' clause must be a strictly positive integer value}} + for (T i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i-ST]; + +#pragma omp target teams distribute simd collapse (2) // expected-note {{as specified in 'collapse' clause}} + foo(); // expected-error {{expected 2 for loops after '#pragma omp target teams distribute simd'}} + return argc; +} + +int main(int argc, char **argv) { +#pragma omp target teams distribute simd collapse // expected-error {{expected '(' after 'collapse'}} + for (int i = 4; i < 12; i++) + argv[0][i] = argv[0][i] - argv[0][i-4]; + +#pragma omp target teams distribute simd collapse ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int i = 4; i < 12; i++) + argv[0][i] = argv[0][i] - argv[0][i-4]; + +#pragma omp target teams distribute simd collapse () // expected-error {{expected expression}} + for (int i = 4; i < 12; i++) + argv[0][i] = argv[0][i] - argv[0][i-4]; + +#pragma omp target teams distribute simd collapse (4 // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-note {{as specified in 'collapse' clause}} + for (int i = 4; i < 12; i++) + argv[0][i] = argv[0][i] - argv[0][i-4]; // expected-error {{expected 4 for loops after '#pragma omp target teams distribute simd', but found only 1}} + +#pragma omp target teams distribute simd collapse (2+2)) // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute simd' are ignored}} expected-note {{as specified in 'collapse' clause}} + for (int i = 4; i < 12; i++) + argv[0][i] = argv[0][i] - argv[0][i-4]; // expected-error {{expected 4 for loops after '#pragma omp target teams distribute simd', but found only 1}} + +#if __cplusplus >= 201103L + // expected-note@+2 {{non-constexpr function 'foobool' cannot be used in a constant expression}} +#endif +#pragma omp target teams distribute simd collapse (foobool(1) > 0 ? 1 : 2) // expected-error {{expression is not an integral constant expression}} + for (int i = 4; i < 12; i++) + argv[0][i] = argv[0][i] - argv[0][i-4]; + +// expected-error@+6 {{expression is not an integral constant expression}} +// expected-error@+5 2 {{directive '#pragma omp target teams distribute simd' cannot contain more than one 'collapse' clause}} +// expected-error@+4 2 {{argument to 'collapse' clause must be a strictly positive integer value}} +#if __cplusplus >= 201103L +// expected-note@+2 {{non-constexpr function 'foobool' cannot be used in a constant expression}} +#endif +#pragma omp target teams distribute simd collapse (foobool(argc)), collapse (true), collapse (-5) + for (int i = 4; i < 12; i++) + argv[0][i] = argv[0][i] - argv[0][i-4]; + +#pragma omp target teams distribute simd collapse (S1) // expected-error {{'S1' does not refer to a value}} + for (int i = 4; i < 12; i++) + argv[0][i] = argv[0][i] - argv[0][i-4]; + +#if __cplusplus >= 201103L + // expected-error@+4 {{integral constant expression must have integral or unscoped enumeration type, not 'char *'}} +#else + // expected-error@+2 {{expression is not an integral constant expression}} +#endif +#pragma omp target teams distribute simd collapse (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int i = 4; i < 12; i++) + argv[0][i] = argv[0][i] - argv[0][i-4]; + +// expected-error@+3 {{statement after '#pragma omp target teams distribute simd' must be a for loop}} +// expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, -1, -2>' requested here}} +#pragma omp target teams distribute simd collapse(collapse(tmain<int, char, -1, -2>(argc, argv) // expected-error 2 {{expected ')'}} expected-note 2 {{to match this '('}} + foo(); + +#pragma omp target teams distribute simd collapse (2) // expected-note {{as specified in 'collapse' clause}} + foo(); // expected-error {{expected 2 for loops after '#pragma omp target teams distribute simd'}} + +// expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, 1, 0>' requested here}} + return tmain<int, char, 1, 0>(argc, argv); +} + diff --git a/test/OpenMP/target_teams_distribute_simd_defaultmap_messages.cpp b/test/OpenMP/target_teams_distribute_simd_defaultmap_messages.cpp new file mode 100644 index 000000000000..3bea411540a2 --- /dev/null +++ b/test/OpenMP/target_teams_distribute_simd_defaultmap_messages.cpp @@ -0,0 +1,58 @@ +// RUN: %clang_cc1 -verify -fopenmp %s + +void foo() { +} + +template <class T, typename S, int N, int ST> +T tmain(T argc, S **argv) { + int i; +#pragma omp target teams distribute simd defaultmap // expected-error {{expected '(' after 'defaultmap'}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd defaultmap ( // expected-error {{expected 'tofrom' in OpenMP clause 'defaultmap'}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd defaultmap () // expected-error {{expected 'tofrom' in OpenMP clause 'defaultmap'}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd defaultmap (tofrom // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-warning {{missing ':' after defaultmap modifier - ignoring}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd defaultmap (tofrom: // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd defaultmap (tofrom) // expected-warning {{missing ':' after defaultmap modifier - ignoring}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd defaultmap (tofrom scalar) // expected-warning {{missing ':' after defaultmap modifier - ignoring}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd defaultmap (tofrom, // expected-error {{expected ')'}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}} expected-warning {{missing ':' after defaultmap modifier - ignoring}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd defaultmap (scalar: // expected-error {{expected ')'}} expected-error {{expected 'tofrom' in OpenMP clause 'defaultmap'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd defaultmap (tofrom, scalar // expected-error {{expected ')'}} expected-warning {{missing ':' after defaultmap modifier - ignoring}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); + + return argc; +} + +int main(int argc, char **argv) { + int i; +#pragma omp target teams distribute simd defaultmap // expected-error {{expected '(' after 'defaultmap'}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd defaultmap ( // expected-error {{expected 'tofrom' in OpenMP clause 'defaultmap'}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd defaultmap () // expected-error {{expected 'tofrom' in OpenMP clause 'defaultmap'}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd defaultmap (tofrom // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-warning {{missing ':' after defaultmap modifier - ignoring}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd defaultmap (tofrom: // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd defaultmap (tofrom) // expected-warning {{missing ':' after defaultmap modifier - ignoring}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd defaultmap (tofrom scalar) // expected-warning {{missing ':' after defaultmap modifier - ignoring}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd defaultmap (tofrom, // expected-error {{expected ')'}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}} expected-warning {{missing ':' after defaultmap modifier - ignoring}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd defaultmap (scalar: // expected-error {{expected ')'}} expected-error {{expected 'tofrom' in OpenMP clause 'defaultmap'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd defaultmap (tofrom, scalar // expected-error {{expected ')'}} expected-warning {{missing ':' after defaultmap modifier - ignoring}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); + + return tmain<int, char, 1, 0>(argc, argv); +} + diff --git a/test/OpenMP/target_teams_distribute_simd_depend_messages.cpp b/test/OpenMP/target_teams_distribute_simd_depend_messages.cpp new file mode 100644 index 000000000000..39d12d8d4d0e --- /dev/null +++ b/test/OpenMP/target_teams_distribute_simd_depend_messages.cpp @@ -0,0 +1,90 @@ +// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - -std=c++11 %s + +void foo() { +} + +bool foobool(int argc) { + return argc; +} + +struct S1; // expected-note {{declared here}} + +class vector { + public: + int operator[](int index) { return 0; } +}; + +int main(int argc, char **argv, char *env[]) { + vector vec; + typedef float V __attribute__((vector_size(16))); + V a; + auto arr = x; // expected-error {{use of undeclared identifier 'x'}} + int i; + +#pragma omp target teams distribute simd depend // expected-error {{expected '(' after 'depend'}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd depend ( // expected-error {{expected 'in', 'out' or 'inout' in OpenMP clause 'depend'}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-warning {{missing ':' after dependency type - ignoring}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd depend () // expected-error {{expected 'in', 'out' or 'inout' in OpenMP clause 'depend'}} expected-warning {{missing ':' after dependency type - ignoring}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd depend (argc // expected-error {{expected 'in', 'out' or 'inout' in OpenMP clause 'depend'}} expected-warning {{missing ':' after dependency type - ignoring}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd depend (source : argc) // expected-error {{expected 'in', 'out' or 'inout' in OpenMP clause 'depend'}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd depend (source) // expected-error {{expected expression}} expected-warning {{missing ':' after dependency type - ignoring}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd depend (in : argc)) // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute simd' are ignored}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd depend (out: ) // expected-error {{expected expression}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd depend (inout : foobool(argc)), depend (in, argc) // expected-error {{expected variable name, array element or array section}} expected-warning {{missing ':' after dependency type - ignoring}} expected-error {{expected expression}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd depend (out :S1) // expected-error {{'S1' does not refer to a value}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd depend(in : argv[1][1] = '2') // expected-error {{expected variable name, array element or array section}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd depend (in : vec[1]) // expected-error {{expected variable name, array element or array section}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd depend (in : argv[0]) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd depend (in : ) // expected-error {{expected expression}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd depend (in : main) // expected-error {{expected variable name, array element or array section}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd depend(in : a[0]) // expected-error{{expected variable name, array element or array section}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd depend (in : vec[1:2]) // expected-error {{ value is not an array or pointer}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd depend (in : argv[ // expected-error {{expected expression}} expected-error {{expected ']'}} expected-error {{expected ')'}} expected-note {{to match this '['}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd depend (in : argv[: // expected-error {{expected expression}} expected-error {{expected ']'}} expected-error {{expected ')'}} expected-note {{to match this '['}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd depend (in : argv[:] // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd depend (in : argv[argc: // expected-error {{expected expression}} expected-error {{expected ']'}} expected-error {{expected ')'}} expected-note {{to match this '['}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd depend (in : argv[argc:argc] // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd depend (in : argv[0:-1]) // expected-error {{section length is evaluated to a negative value -1}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd depend (in : argv[-1:0]) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd depend (in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd depend (in : argv[3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd depend(in:a[0:1]) // expected-error {{subscripted value is not an array or pointer}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd depend(in:argv[argv[:2]:1]) // expected-error {{OpenMP array section is not allowed here}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd depend(in:argv[0:][:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd depend(in:env[0:][:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is an array of unknown bound}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd depend(in : argv[ : argc][1 : argc - 1]) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd depend(in : arr[0]) + for (i = 0; i < argc; ++i) foo(); + + return 0; +} diff --git a/test/OpenMP/target_teams_distribute_simd_device_messages.cpp b/test/OpenMP/target_teams_distribute_simd_device_messages.cpp new file mode 100644 index 000000000000..e9246cb29def --- /dev/null +++ b/test/OpenMP/target_teams_distribute_simd_device_messages.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -verify -fopenmp %s + +void foo() { +} + +bool foobool(int argc) { + return argc; +} + +struct S1; // expected-note {{declared here}} + +int main(int argc, char **argv) { + int i; +#pragma omp target teams distribute simd device // expected-error {{expected '(' after 'device'}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd device ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd device () // expected-error {{expected expression}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd device (argc // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd device (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute simd' are ignored}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd device (argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd device (argc + argc) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd device (argc), device (argc+1) // expected-error {{directive '#pragma omp target teams distribute simd' cannot contain more than one 'device' clause}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd device (S1) // expected-error {{'S1' does not refer to a value}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd device (-2) // expected-error {{argument to 'device' clause must be a non-negative integer value}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd device (-10u) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd device (3.14) // expected-error {{expression must have integral or unscoped enumeration type, not 'double'}} + for (i = 0; i < argc; ++i) foo(); + + return 0; +} diff --git a/test/OpenMP/target_teams_distribute_simd_dist_schedule_messages.cpp b/test/OpenMP/target_teams_distribute_simd_dist_schedule_messages.cpp new file mode 100644 index 000000000000..9b9239d64e9d --- /dev/null +++ b/test/OpenMP/target_teams_distribute_simd_dist_schedule_messages.cpp @@ -0,0 +1,84 @@ +// RUN: %clang_cc1 -verify -fopenmp %s + +void foo() { +} + +bool foobool(int argc) { + return argc; +} + +struct S1; // expected-note {{declared here}} expected-note {{declared here}} + +template <class T, int N> +T tmain(T argc) { + T b = argc, c, d, e, f, g; + char ** argv; + static T a; +// CHECK: static T a; + +#pragma omp target teams distribute simd dist_schedule // expected-error {{expected '(' after 'dist_schedule'}} + for (int i = 0; i < 10; ++i) foo(); + +#pragma omp target teams distribute simd dist_schedule ( // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int i = 0; i < 10; ++i) foo(); + +#pragma omp target teams distribute simd dist_schedule () // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}} + for (int i = 0; i < 10; ++i) foo(); + +#pragma omp target teams distribute simd dist_schedule (static // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int i = 0; i < 10; ++i) foo(); + +#pragma omp target teams distribute simd dist_schedule (static, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int i = 0; i < 10; ++i) foo(); + +#pragma omp target teams distribute simd dist_schedule (argc)) // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}} expected-warning {{extra tokens at the end of '#pragma omp target teams distribute simd' are ignored}} + for (int i = 0; i < 10; ++i) foo(); + +#pragma omp target teams distribute simd dist_schedule (static, argc > 0 ? argv[1] : argv[2]) // expected-error2 {{expression must have integral or unscoped enumeration type, not 'char *'}} + for (int i = 0; i < 10; ++i) foo(); + +#pragma omp target teams distribute simd dist_schedule (static), dist_schedule (static, 1) // expected-error {{directive '#pragma omp target teams distribute simd' cannot contain more than one 'dist_schedule' clause}} + for (int i = 0; i < 10; ++i) foo(); + +#pragma omp target teams distribute simd dist_schedule (static, S1) // expected-error {{'S1' does not refer to a value}} + for (int i = 0; i < 10; ++i) foo(); + +#pragma omp target teams distribute simd dist_schedule (static, argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error3 {{expression must have integral or unscoped enumeration type, not 'char *'}} + for (int i = 0; i < 10; ++i) foo(); + + return T(); +} + +int main(int argc, char **argv) { +#pragma omp target teams distribute simd dist_schedule // expected-error {{expected '(' after 'dist_schedule'}} + for (int i = 0; i < 10; ++i) foo(); + +#pragma omp target teams distribute simd dist_schedule ( // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int i = 0; i < 10; ++i) foo(); + +#pragma omp target teams distribute simd dist_schedule () // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}} + for (int i = 0; i < 10; ++i) foo(); + +#pragma omp target teams distribute simd dist_schedule (static // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int i = 0; i < 10; ++i) foo(); + +#pragma omp target teams distribute simd dist_schedule (static, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int i = 0; i < 10; ++i) foo(); + +#pragma omp target teams distribute simd dist_schedule (argc)) // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}} expected-warning {{extra tokens at the end of '#pragma omp target teams distribute simd' are ignored}} + for (int i = 0; i < 10; ++i) foo(); + +#pragma omp target teams distribute simd dist_schedule (static, argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} + for (int i = 0; i < 10; ++i) foo(); + +#pragma omp target teams distribute simd dist_schedule (static), dist_schedule (static, 1) // expected-error {{directive '#pragma omp target teams distribute simd' cannot contain more than one 'dist_schedule' clause}} + for (int i = 0; i < 10; ++i) foo(); + +#pragma omp target teams distribute simd dist_schedule (static, S1) // expected-error {{'S1' does not refer to a value}} + for (int i = 0; i < 10; ++i) foo(); + +#pragma omp target teams distribute simd dist_schedule (static, argv[1]=2) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int i = 0; i < 10; ++i) foo(); + + return (tmain<int, 5>(argc) + tmain<char, 1>(argv[0][0])); // expected-note {{in instantiation of function template specialization 'tmain<int, 5>' requested here}} expected-note {{in instantiation of function template specialization 'tmain<char, 1>' requested here}} +} diff --git a/test/OpenMP/target_teams_distribute_simd_firstprivate_messages.cpp b/test/OpenMP/target_teams_distribute_simd_firstprivate_messages.cpp new file mode 100644 index 000000000000..b9b039efd929 --- /dev/null +++ b/test/OpenMP/target_teams_distribute_simd_firstprivate_messages.cpp @@ -0,0 +1,134 @@ +// RUN: %clang_cc1 -verify -fopenmp %s + +void foo() { +} + +bool foobool(int argc) { + return argc; +} + +struct S1; // expected-note {{declared here}} expected-note{{forward declaration of 'S1'}} +extern S1 a; +class S2 { + mutable int a; + +public: + S2() : a(0) {} + S2(const S2 &s2) : a(s2.a) {} + static float S2s; + static const float S2sc; +}; +const float S2::S2sc = 0; +const S2 b; +const S2 ba[5]; +class S3 { + int a; + S3 &operator=(const S3 &s3); + +public: + S3() : a(0) {} // expected-note {{candidate constructor not viable: requires 0 arguments, but 1 was provided}} expected-note {{candidate constructor not viable: requires 0 arguments, but 1 was provided}} + S3(S3 &s3) : a(s3.a) {} // expected-note {{candidate constructor not viable: 1st argument ('const S3') would lose const qualifier}} expected-note {{candidate constructor not viable: 1st argument ('const S3') would lose const qualifier}} +}; +const S3 c; +const S3 ca[5]; +extern const int f; +class S4 { + int a; + S4(); + S4(const S4 &s4); +public: + S4(int v):a(v) { } +}; +class S5 { + int a; + S5():a(0) {} + S5(const S5 &s5):a(s5.a) { } +public: + S5(int v):a(v) { } +}; +class S6 { + int a; +public: + S6() : a(0) { } +}; + +S3 h; +#pragma omp threadprivate(h) // expected-note {{defined as threadprivate or thread local}} + +int main(int argc, char **argv) { + const int d = 5; + const int da[5] = { 0 }; + S4 e(4); + S5 g(5); + S6 p; + int i; + int &j = i; + +#pragma omp target teams distribute simd firstprivate // expected-error {{expected '(' after 'firstprivate'}} + for (i = 0; i < argc; ++i) foo(); + +#pragma omp target teams distribute simd firstprivate ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); + +#pragma omp target teams distribute simd firstprivate () // expected-error {{expected expression}} + for (i = 0; i < argc; ++i) foo(); + +#pragma omp target teams distribute simd firstprivate (argc // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); + +#pragma omp target teams distribute simd firstprivate (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); + +#pragma omp target teams distribute simd firstprivate (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}} + for (i = 0; i < argc; ++i) foo(); + +#pragma omp target teams distribute simd firstprivate (argc) + for (i = 0; i < argc; ++i) foo(); + +#pragma omp target teams distribute simd firstprivate (S1) // expected-error {{'S1' does not refer to a value}} + for (i = 0; i < argc; ++i) foo(); + +#pragma omp target teams distribute simd firstprivate (a, b, c, d, f) // expected-error {{firstprivate variable with incomplete type 'S1'}} expected-error {{no matching constructor for initialization of 'S3'}} + for (i = 0; i < argc; ++i) foo(); + +#pragma omp target teams distribute simd firstprivate (argv[1]) // expected-error {{expected variable name}} + for (i = 0; i < argc; ++i) foo(); + +#pragma omp target teams distribute simd firstprivate(ba) + for (i = 0; i < argc; ++i) foo(); + +#pragma omp target teams distribute simd firstprivate(ca) // expected-error {{no matching constructor for initialization of 'S3'}} + for (i = 0; i < argc; ++i) foo(); + +#pragma omp target teams distribute simd firstprivate(da) + for (i = 0; i < argc; ++i) foo(); + +#pragma omp target teams distribute simd firstprivate(S2::S2s) + for (i = 0; i < argc; ++i) foo(); + +#pragma omp target teams distribute simd firstprivate(S2::S2sc) + for (i = 0; i < argc; ++i) foo(); + +#pragma omp target teams distribute simd firstprivate(h) // expected-error {{threadprivate or thread local variable cannot be firstprivate}} + for (i = 0; i < argc; ++i) foo(); + +#pragma omp target teams distribute simd private(i), firstprivate(i) // expected-error {{private variable cannot be firstprivate}} expected-note 2 {{defined as private}} + for (i = 0; i < argc; ++i) foo(); // expected-error {{loop iteration variable in the associated loop of 'omp target teams distribute simd' directive may not be private, predetermined as linear}} + +#pragma omp target teams distribute simd firstprivate(i) + for (j = 0; j < argc; ++j) foo(); + +#pragma omp target teams distribute simd firstprivate(i) // expected-note {{defined as firstprivate}} + for (i = 0; i < argc; ++i) foo(); // expected-error {{loop iteration variable in the associated loop of 'omp target teams distribute simd' directive may not be firstprivate, predetermined as linear}} + +#pragma omp target teams distribute simd firstprivate(j) + for (i = 0; i < argc; ++i) foo(); + +#pragma omp target teams distribute simd lastprivate(argc), firstprivate(argc) // OK + for (i = 0; i < argc; ++i) foo(); + +#pragma omp target teams distribute simd firstprivate(argc) map(argc) // expected-error {{firstprivate variable cannot be in a map clause in '#pragma omp target teams distribute simd' directive}} expected-note {{defined as firstprivate}} + for (i = 0; i < argc; ++i) foo(); + + return 0; +} diff --git a/test/OpenMP/target_teams_distribute_simd_if_messages.cpp b/test/OpenMP/target_teams_distribute_simd_if_messages.cpp new file mode 100644 index 000000000000..6cb2ad44aa11 --- /dev/null +++ b/test/OpenMP/target_teams_distribute_simd_if_messages.cpp @@ -0,0 +1,101 @@ +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ferror-limit 100 %s + +void foo() { +} + +bool foobool(int argc) { + return argc; +} + +struct S1; // expected-note {{declared here}} + +template <class T, class S> // expected-note {{declared here}} +int tmain(T argc, S **argv) { + T i; +#pragma omp target teams distribute simd if // expected-error {{expected '(' after 'if'}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd if ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd if () // expected-error {{expected expression}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd if (argc // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd if (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute simd' are ignored}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd if (argc > 0 ? argv[1] : argv[2]) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd if (foobool(argc)), if (true) // expected-error {{directive '#pragma omp target teams distribute simd' cannot contain more than one 'if' clause}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd if (S) // expected-error {{'S' does not refer to a value}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd if (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd if (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd if(argc) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd if(target // expected-error {{use of undeclared identifier 'target'}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd if(target : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd if(target : argc // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd if(target: argc) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd if(target : argc) if (distribute:argc) // expected-error {{directive name modifier 'distribute' is not allowed for '#pragma omp target teams distribute simd'}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd if(target: argc) if (target:argc) // expected-error {{directive '#pragma omp target teams distribute simd' cannot contain more than one 'if' clause with 'target' name modifier}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd if(target: argc) if (argc) // expected-note {{previous clause with directive name modifier specified here}} expected-error {{no more 'if' clause is allowed}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd if(distribute : argc) // expected-error {{directive name modifier 'distribute' is not allowed for '#pragma omp target teams distribute simd'}} + for (i = 0; i < argc; ++i) foo(); + + return 0; +} + +int main(int argc, char **argv) { + int i; +#pragma omp target teams distribute simd if // expected-error {{expected '(' after 'if'}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd if ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd if () // expected-error {{expected expression}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd if (argc // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd if (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute simd' are ignored}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd if (argc > 0 ? argv[1] : argv[2]) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd if (foobool(argc)), if (true) // expected-error {{directive '#pragma omp target teams distribute simd' cannot contain more than one 'if' clause}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd if (S1) // expected-error {{'S1' does not refer to a value}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd if (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd if (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd if (1 0) // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd if(if(tmain(argc, argv) // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd if(target // expected-error {{use of undeclared identifier 'target'}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd if(target : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd if(target: argc // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd if(target: argc) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd if(target : argc) if (distribute:argc) // expected-error {{directive name modifier 'distribute' is not allowed for '#pragma omp target teams distribute simd'}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd if(target: argc) if (target:argc) // expected-error {{directive '#pragma omp target teams distribute simd' cannot contain more than one 'if' clause with 'target' name modifier}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd if(target: argc) if (argc) // expected-note {{previous clause with directive name modifier specified here}} expected-error {{no more 'if' clause is allowed}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd if(distribute : argc) // expected-error {{directive name modifier 'distribute' is not allowed for '#pragma omp target teams distribute simd'}} + for (i = 0; i < argc; ++i) foo(); + + return tmain(argc, argv); +} diff --git a/test/OpenMP/target_teams_distribute_simd_is_device_ptr_ast_print.cpp b/test/OpenMP/target_teams_distribute_simd_is_device_ptr_ast_print.cpp new file mode 100644 index 000000000000..61aede4cb9e6 --- /dev/null +++ b/test/OpenMP/target_teams_distribute_simd_is_device_ptr_ast_print.cpp @@ -0,0 +1,318 @@ +// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ast-print %s | FileCheck %s +// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s +// expected-no-diagnostics + +#ifndef HEADER +#define HEADER +struct ST { + int *a; +}; +typedef int arr[10]; +typedef ST STarr[10]; +struct SA { + const int da[5] = { 0 }; + ST g[10]; + STarr &rg = g; + int i; + int &j = i; + int *k = &j; + int *&z = k; + int aa[10]; + arr &raa = aa; + void func(int arg) { +#pragma omp target teams distribute simd is_device_ptr(k) + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(z) + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(aa) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(raa) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(g) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(rg) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(da) // OK + for (int i=0; i<100; i++) + ; + return; + } +}; +// CHECK: struct SA +// CHECK-NEXT: const int da[5] = {0}; +// CHECK-NEXT: ST g[10]; +// CHECK-NEXT: STarr &rg = this->g; +// CHECK-NEXT: int i; +// CHECK-NEXT: int &j = this->i; +// CHECK-NEXT: int *k = &this->j; +// CHECK-NEXT: int *&z = this->k; +// CHECK-NEXT: int aa[10]; +// CHECK-NEXT: arr &raa = this->aa; +// CHECK-NEXT: func( +// CHECK-NEXT: #pragma omp target teams distribute simd is_device_ptr(this->k) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +// CHECK-NEXT: #pragma omp target teams distribute simd is_device_ptr(this->z) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +// CHECK-NEXT: #pragma omp target teams distribute simd is_device_ptr(this->aa) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +// CHECK-NEXT: #pragma omp target teams distribute simd is_device_ptr(this->raa) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +// CHECK-NEXT: #pragma omp target teams distribute simd is_device_ptr(this->g) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +// CHECK-NEXT: #pragma omp target teams distribute simd is_device_ptr(this->rg) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +// CHECK-NEXT: #pragma omp target teams distribute simd is_device_ptr(this->da) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; + +struct SB { + unsigned A; + unsigned B; + float Arr[100]; + float *Ptr; + float *foo() { + return &Arr[0]; + } +}; + +struct SC { + unsigned A : 2; + unsigned B : 3; + unsigned C; + unsigned D; + float Arr[100]; + SB S; + SB ArrS[100]; + SB *PtrS; + SB *&RPtrS; + float *Ptr; + + SC(SB *&_RPtrS) : RPtrS(_RPtrS) {} +}; + +union SD { + unsigned A; + float B; +}; + +struct S1; +extern S1 a; +class S2 { + mutable int a; +public: + S2():a(0) { } + S2(S2 &s2):a(s2.a) { } + static float S2s; + static const float S2sc; +}; +const float S2::S2sc = 0; +const S2 b; +const S2 ba[5]; +class S3 { + int a; +public: + S3():a(0) { } + S3(S3 &s3):a(s3.a) { } +}; +const S3 c; +const S3 ca[5]; +extern const int f; +class S4 { + int a; + S4(); + S4(const S4 &s4); +public: + S4(int v):a(v) { } +}; +class S5 { + int a; + S5():a(0) {} + S5(const S5 &s5):a(s5.a) { } +public: + S5(int v):a(v) { } +}; + +S3 h; +#pragma omp threadprivate(h) + +typedef struct { + int a; +} S6; + +template <typename T> +T tmain(T argc) { + const T da[5] = { 0 }; + S6 h[10]; + auto &rh = h; + T i; + T &j = i; + T *k = &j; + T *&z = k; + T aa[10]; + auto &raa = aa; +#pragma omp target teams distribute simd is_device_ptr(k) + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(z) + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(aa) + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(raa) + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(h) + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(rh) + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(da) + for (int i=0; i<100; i++) + ; + return 0; +} + +// CHECK: template<> int tmain<int>(int argc) { +// CHECK-NEXT: const int da[5] = {0}; +// CHECK-NEXT: S6 h[10]; +// CHECK-NEXT: auto &rh = h; +// CHECK-NEXT: int i; +// CHECK-NEXT: int &j = i; +// CHECK-NEXT: int *k = &j; +// CHECK-NEXT: int *&z = k; +// CHECK-NEXT: int aa[10]; +// CHECK-NEXT: auto &raa = aa; +// CHECK-NEXT: #pragma omp target teams distribute simd is_device_ptr(k) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +// CHECK-NEXT: #pragma omp target teams distribute simd is_device_ptr(z) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +// CHECK-NEXT: #pragma omp target teams distribute simd is_device_ptr(aa) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +// CHECK-NEXT: #pragma omp target teams distribute simd is_device_ptr(raa) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +// CHECK-NEXT: #pragma omp target teams distribute simd is_device_ptr(h) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +// CHECK-NEXT: #pragma omp target teams distribute simd is_device_ptr(rh) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +// CHECK-NEXT: #pragma omp target teams distribute simd is_device_ptr(da) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; + +// CHECK: template<> int *tmain<int *>(int *argc) { +// CHECK-NEXT: int *const da[5] = {0}; +// CHECK-NEXT: S6 h[10]; +// CHECK-NEXT: auto &rh = h; +// CHECK-NEXT: int *i; +// CHECK-NEXT: int *&j = i; +// CHECK-NEXT: int **k = &j; +// CHECK-NEXT: int **&z = k; +// CHECK-NEXT: int *aa[10]; +// CHECK-NEXT: auto &raa = aa; +// CHECK-NEXT: #pragma omp target teams distribute simd is_device_ptr(k) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +// CHECK-NEXT: #pragma omp target teams distribute simd is_device_ptr(z) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +// CHECK-NEXT: #pragma omp target teams distribute simd is_device_ptr(aa) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +// CHECK-NEXT: #pragma omp target teams distribute simd is_device_ptr(raa) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +// CHECK-NEXT: #pragma omp target teams distribute simd is_device_ptr(h) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +// CHECK-NEXT: #pragma omp target teams distribute simd is_device_ptr(rh) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +// CHECK-NEXT: #pragma omp target teams distribute simd is_device_ptr(da) +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; + +// CHECK-LABEL: int main(int argc, char **argv) { +int main(int argc, char **argv) { + const int da[5] = { 0 }; + S6 h[10]; + auto &rh = h; + int i; + int &j = i; + int *k = &j; + int *&z = k; + int aa[10]; + auto &raa = aa; +// CHECK-NEXT: const int da[5] = {0}; +// CHECK-NEXT: S6 h[10]; +// CHECK-NEXT: auto &rh = h; +// CHECK-NEXT: int i; +// CHECK-NEXT: int &j = i; +// CHECK-NEXT: int *k = &j; +// CHECK-NEXT: int *&z = k; +// CHECK-NEXT: int aa[10]; +// CHECK-NEXT: auto &raa = aa; +#pragma omp target teams distribute simd is_device_ptr(k) +// CHECK-NEXT: #pragma omp target teams distribute simd is_device_ptr(k) + for (int i=0; i<100; i++) + ; +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +#pragma omp target teams distribute simd is_device_ptr(z) +// CHECK-NEXT: #pragma omp target teams distribute simd is_device_ptr(z) + for (int i=0; i<100; i++) + ; +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +#pragma omp target teams distribute simd is_device_ptr(aa) +// CHECK-NEXT: #pragma omp target teams distribute simd is_device_ptr(aa) + for (int i=0; i<100; i++) + ; +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +#pragma omp target teams distribute simd is_device_ptr(raa) +// CHECK-NEXT: #pragma omp target teams distribute simd is_device_ptr(raa) + for (int i=0; i<100; i++) + ; +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +#pragma omp target teams distribute simd is_device_ptr(h) +// CHECK-NEXT: #pragma omp target teams distribute simd is_device_ptr(h) + for (int i=0; i<100; i++) + ; +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +#pragma omp target teams distribute simd is_device_ptr(rh) +// CHECK-NEXT: #pragma omp target teams distribute simd is_device_ptr(rh) + for (int i=0; i<100; i++) + ; +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; +#pragma omp target teams distribute simd is_device_ptr(da) +// CHECK-NEXT: #pragma omp target teams distribute simd is_device_ptr(da) + for (int i=0; i<100; i++) + ; +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK-NEXT: ; + return tmain<int>(argc) + *tmain<int *>(&argc); +} +#endif diff --git a/test/OpenMP/target_teams_distribute_simd_is_device_ptr_messages.cpp b/test/OpenMP/target_teams_distribute_simd_is_device_ptr_messages.cpp new file mode 100644 index 000000000000..013b703a91e9 --- /dev/null +++ b/test/OpenMP/target_teams_distribute_simd_is_device_ptr_messages.cpp @@ -0,0 +1,337 @@ +// RUN: %clang_cc1 -std=c++11 -verify -fopenmp %s +struct ST { + int *a; +}; +typedef int arr[10]; +typedef ST STarr[10]; +struct SA { + const int d = 5; + const int da[5] = { 0 }; + ST e; + ST g[10]; + STarr &rg = g; + int i; + int &j = i; + int *k = &j; + int *&z = k; + int aa[10]; + arr &raa = aa; + void func(int arg) { +#pragma omp target teams distribute simd is_device_ptr // expected-error {{expected '(' after 'is_device_ptr'}} + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}} + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr() // expected-error {{expected expression}} + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(alloc) // expected-error {{use of undeclared identifier 'alloc'}} + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(arg // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(i) // expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(j) // expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(k) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(z) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(aa) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(raa) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(e) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(g) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(rg) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(k,i,j) // expected-error2 {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(d) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(da) // OK + for (int i=0; i<100; i++) + ; + return; + } +}; +struct SB { + unsigned A; + unsigned B; + float Arr[100]; + float *Ptr; + float *foo() { + return &Arr[0]; + } +}; + +struct SC { + unsigned A : 2; + unsigned B : 3; + unsigned C; + unsigned D; + float Arr[100]; + SB S; + SB ArrS[100]; + SB *PtrS; + SB *&RPtrS; + float *Ptr; + + SC(SB *&_RPtrS) : RPtrS(_RPtrS) {} +}; + +union SD { + unsigned A; + float B; +}; + +struct S1; +extern S1 a; +class S2 { + mutable int a; +public: + S2():a(0) { } + S2(S2 &s2):a(s2.a) { } + static float S2s; + static const float S2sc; +}; +const float S2::S2sc = 0; +const S2 b; +const S2 ba[5]; +class S3 { + int a; +public: + S3():a(0) { } + S3(S3 &s3):a(s3.a) { } +}; +const S3 c; +const S3 ca[5]; +extern const int f; +class S4 { + int a; + S4(); + S4(const S4 &s4); +public: + S4(int v):a(v) { } +}; +class S5 { + int a; + S5():a(0) {} + S5(const S5 &s5):a(s5.a) { } +public: + S5(int v):a(v) { } +}; + +S3 h; +#pragma omp threadprivate(h) + +typedef struct { + int a; +} S6; + +template <typename T, int I> +T tmain(T argc) { + const T d = 5; + const T da[5] = { 0 }; + S4 e(4); + S5 g(5); + S6 h[10]; + auto &rh = h; + T i; + T &j = i; + T *k = &j; + T *&z = k; + T aa[10]; + auto &raa = aa; + S6 *ps; +#pragma omp target teams distribute simd is_device_ptr // expected-error {{expected '(' after 'is_device_ptr'}} + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}} + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr() // expected-error {{expected expression}} + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(alloc) // expected-error {{use of undeclared identifier 'alloc'}} + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(i) // expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(j) // expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(k) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(z) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(aa) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(raa) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(e) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(g) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(h) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(rh) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(k,i,j) // expected-error2 {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(d) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(da) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd map(ps) is_device_ptr(ps) // expected-error{{variable already marked as mapped in current construct}} expected-note{{used here}} + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(ps) map(ps) // expected-error{{variable already marked as mapped in current construct}} expected-note{{used here}} + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd map(ps->a) is_device_ptr(ps) // expected-error{{variable already marked as mapped in current construct}} expected-note{{used here}} + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(ps) map(ps->a) // expected-error{{pointer cannot be mapped along with a section derived from itself}} expected-note{{used here}} + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(ps) firstprivate(ps) // expected-error{{firstprivate variable cannot be in a is_device_ptr clause in '#pragma omp target teams distribute simd' directive}} + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd firstprivate(ps) is_device_ptr(ps) // expected-error{{firstprivate variable cannot be in a is_device_ptr clause in '#pragma omp target teams distribute simd' directive}} expected-note{{defined as firstprivate}} + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(ps) private(ps) // expected-error{{private variable cannot be in a is_device_ptr clause in '#pragma omp target teams distribute simd' directive}} + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd private(ps) is_device_ptr(ps) // expected-error{{private variable cannot be in a is_device_ptr clause in '#pragma omp target teams distribute simd' directive}} expected-note{{defined as private}} + for (int i=0; i<100; i++) + ; + return 0; +} + +int main(int argc, char **argv) { + const int d = 5; + const int da[5] = { 0 }; + S4 e(4); + S5 g(5); + S6 h[10]; + auto &rh = h; + int i; + int &j = i; + int *k = &j; + int *&z = k; + int aa[10]; + auto &raa = aa; + S6 *ps; +#pragma omp target teams distribute simd is_device_ptr // expected-error {{expected '(' after 'is_device_ptr'}} + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}} + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr() // expected-error {{expected expression}} + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(alloc) // expected-error {{use of undeclared identifier 'alloc'}} + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(i) // expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(j) // expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(k) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(z) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(aa) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(raa) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(e) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(g) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(h) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(rh) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(k,i,j) // expected-error2 {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(d) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}} + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(da) // OK + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd map(ps) is_device_ptr(ps) // expected-error{{variable already marked as mapped in current construct}} expected-note{{used here}} + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(ps) map(ps) // expected-error{{variable already marked as mapped in current construct}} expected-note{{used here}} + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd map(ps->a) is_device_ptr(ps) // expected-error{{variable already marked as mapped in current construct}} expected-note{{used here}} + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(ps) map(ps->a) // expected-error{{pointer cannot be mapped along with a section derived from itself}} expected-note{{used here}} + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(ps) firstprivate(ps) // expected-error{{firstprivate variable cannot be in a is_device_ptr clause in '#pragma omp target teams distribute simd' directive}} + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd firstprivate(ps) is_device_ptr(ps) // expected-error{{firstprivate variable cannot be in a is_device_ptr clause in '#pragma omp target teams distribute simd' directive}} expected-note{{defined as firstprivate}} + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd is_device_ptr(ps) private(ps) // expected-error{{private variable cannot be in a is_device_ptr clause in '#pragma omp target teams distribute simd' directive}} + for (int i=0; i<100; i++) + ; +#pragma omp target teams distribute simd private(ps) is_device_ptr(ps) // expected-error{{private variable cannot be in a is_device_ptr clause in '#pragma omp target teams distribute simd' directive}} expected-note{{defined as private}} + for (int i=0; i<100; i++) + ; + return tmain<int, 3>(argc); // expected-note {{in instantiation of function template specialization 'tmain<int, 3>' requested here}} +} diff --git a/test/OpenMP/target_teams_distribute_simd_lastprivate_messages.cpp b/test/OpenMP/target_teams_distribute_simd_lastprivate_messages.cpp new file mode 100644 index 000000000000..3b533e2e5484 --- /dev/null +++ b/test/OpenMP/target_teams_distribute_simd_lastprivate_messages.cpp @@ -0,0 +1,233 @@ +// RUN: %clang_cc1 -verify -fopenmp %s + +void foo() { +} + +bool foobool(int argc) { + return argc; +} + +struct S1; // expected-note 2 {{declared here}} expected-note 2 {{forward declaration of 'S1'}} +extern S1 a; +class S2 { + mutable int a; + +public: + S2() : a(0) {} + S2(S2 &s2) : a(s2.a) {} + const S2 &operator =(const S2&) const; + S2 &operator =(const S2&); + static float S2s; // expected-note {{static data member is predetermined as shared}} + static const float S2sc; +}; +const float S2::S2sc = 0; // expected-note {{static data member is predetermined as shared}} +const S2 b; +const S2 ba[5]; +class S3 { + int a; + S3 &operator=(const S3 &s3); // expected-note 2 {{implicitly declared private here}} + +public: + S3() : a(0) {} + S3(S3 &s3) : a(s3.a) {} +}; +const S3 c; // expected-note {{global variable is predetermined as shared}} +const S3 ca[5]; // expected-note {{global variable is predetermined as shared}} +extern const int f; // expected-note {{global variable is predetermined as shared}} +class S4 { + int a; + S4(); // expected-note 3 {{implicitly declared private here}} + S4(const S4 &s4); + +public: + S4(int v) : a(v) {} +}; +class S5 { + int a; + S5() : a(0) {} // expected-note {{implicitly declared private here}} + +public: + S5(const S5 &s5) : a(s5.a) {} + S5(int v) : a(v) {} +}; +class S6 { + int a; + S6() : a(0) {} + +public: + S6(const S6 &s6) : a(s6.a) {} + S6(int v) : a(v) {} +}; + +S3 h; +#pragma omp threadprivate(h) // expected-note 2 {{defined as threadprivate or thread local}} + +template <class I, class C> +int foomain(int argc, char **argv) { + I e(4); + I g(5); + int i; + int &j = i; +#pragma omp target teams distribute simd lastprivate // expected-error {{expected '(' after 'lastprivate'}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd lastprivate( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd lastprivate() // expected-error {{expected expression}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd lastprivate(argc // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd lastprivate(argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd lastprivate(argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd lastprivate(argc) + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd lastprivate(S1) // expected-error {{'S1' does not refer to a value}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd lastprivate(a, b) // expected-error {{lastprivate variable with incomplete type 'S1'}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd lastprivate(argv[1]) // expected-error {{expected variable name}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd lastprivate(e, g) // expected-error 2 {{calling a private constructor of class 'S4'}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd lastprivate(h) // expected-error {{threadprivate or thread local variable cannot be lastprivate}} + for (int k = 0; k < argc; ++k) ++k; + + int v = 0; +#pragma omp target teams distribute simd lastprivate(i) + for (int k = 0; k < argc; ++k) { + i = k; + v += i; + } + +#pragma omp target teams distribute simd lastprivate(j) private(i) + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd lastprivate(i) + for (int k = 0; k < argc; ++k) ++k; + + return 0; +} + +void bar(S4 a[2]) { +#pragma omp target teams distribute simd lastprivate(a) + for (int i = 0; i < 2; ++i) foo(); +} + +namespace A { +double x; +#pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}} +} +namespace B { +using A::x; +} + +int main(int argc, char **argv) { + const int d = 5; // expected-note {{constant variable is predetermined as shared}} + const int da[5] = {0}; // expected-note {{constant variable is predetermined as shared}} + S4 e(4); + S5 g(5); + S3 m; + S6 n(2); + int i; + int &j = i; + float k; +#pragma omp target teams distribute simd lastprivate // expected-error {{expected '(' after 'lastprivate'}} + for (i = 0; i < argc; ++i) foo(); + +#pragma omp target teams distribute simd lastprivate( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); + +#pragma omp target teams distribute simd lastprivate() // expected-error {{expected expression}} + for (i = 0; i < argc; ++i) foo(); + +#pragma omp target teams distribute simd lastprivate(argc // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); + +#pragma omp target teams distribute simd lastprivate(argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); + +#pragma omp target teams distribute simd lastprivate(argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}} + for (i = 0; i < argc; ++i) foo(); + +#pragma omp target teams distribute simd lastprivate(argc) + for (i = 0; i < argc; ++i) foo(); + +#pragma omp target teams distribute simd lastprivate(S1) // expected-error {{'S1' does not refer to a value}} + for (i = 0; i < argc; ++i) foo(); + +#pragma omp target teams distribute simd lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be lastprivate}} + for (i = 0; i < argc; ++i) foo(); + +#pragma omp target teams distribute simd lastprivate(argv[1]) // expected-error {{expected variable name}} + for (i = 0; i < argc; ++i) foo(); + +#pragma omp target teams distribute simd lastprivate(2 * 2) // expected-error {{expected variable name}} + for (i = 0; i < argc; ++i) foo(); + +#pragma omp target teams distribute simd lastprivate(ba) + for (i = 0; i < argc; ++i) foo(); + +#pragma omp target teams distribute simd lastprivate(ca) // expected-error {{shared variable cannot be lastprivate}} + for (i = 0; i < argc; ++i) foo(); + +#pragma omp target teams distribute simd lastprivate(da) // expected-error {{shared variable cannot be lastprivate}} + for (i = 0; i < argc; ++i) foo(); + + int xa; +#pragma omp target teams distribute simd lastprivate(xa) // OK + for (i = 0; i < argc; ++i) foo(); + +#pragma omp target teams distribute simd lastprivate(S2::S2s) // expected-error {{shared variable cannot be lastprivate}} + for (i = 0; i < argc; ++i) foo(); + +#pragma omp target teams distribute simd lastprivate(S2::S2sc) // expected-error {{shared variable cannot be lastprivate}} + for (i = 0; i < argc; ++i) foo(); + +#pragma omp target teams distribute simd lastprivate(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}} + for (i = 0; i < argc; ++i) foo(); + +#pragma omp target teams distribute simd lastprivate(m) // expected-error {{'operator=' is a private member of 'S3'}} + for (i = 0; i < argc; ++i) foo(); + +#pragma omp target teams distribute simd lastprivate(h) // expected-error {{threadprivate or thread local variable cannot be lastprivate}} + for (i = 0; i < argc; ++i) foo(); + +#pragma omp target teams distribute simd lastprivate(B::x) // expected-error {{threadprivate or thread local variable cannot be lastprivate}} + for (i = 0; i < argc; ++i) foo(); + +#pragma omp target teams distribute simd private(xa), lastprivate(xa) // expected-error {{private variable cannot be lastprivate}} expected-note {{defined as private}} + for (i = 0; i < argc; ++i) foo(); + +#pragma omp target teams distribute simd lastprivate(xa) + for (i = 0; i < argc; ++i) foo(); + +#pragma omp target teams distribute simd lastprivate(j) + for (i = 0; i < argc; ++i) foo(); + +#pragma omp target teams distribute simd firstprivate(m) lastprivate(m) // expected-error {{'operator=' is a private member of 'S3'}} + for (i = 0; i < argc; ++i) foo(); + +#pragma omp target teams distribute simd lastprivate(n) firstprivate(n) // OK + for (i = 0; i < argc; ++i) foo(); + + static int si; +#pragma omp target teams distribute simd lastprivate(si) // OK + for (i = 0; i < argc; ++i) si = i + 1; + +#pragma omp target teams distribute simd lastprivate(k) map(k) // expected-error {{lastprivate variable cannot be in a map clause in '#pragma omp target teams distribute simd' directive}} expected-note {{defined as lastprivate}} + for (i = 0; i < argc; ++i) foo(); + + return foomain<S4, S5>(argc, argv); // expected-note {{in instantiation of function template specialization 'foomain<S4, S5>' requested here}} +} diff --git a/test/OpenMP/target_teams_distribute_simd_linear_messages.cpp b/test/OpenMP/target_teams_distribute_simd_linear_messages.cpp new file mode 100644 index 000000000000..8db57a0f3665 --- /dev/null +++ b/test/OpenMP/target_teams_distribute_simd_linear_messages.cpp @@ -0,0 +1,248 @@ +// RUN: %clang_cc1 -verify -fopenmp %s + +namespace X { + int x; +}; + +struct B { + static int ib; // expected-note {{'B::ib' declared here}} + static int bfoo() { return 8; } +}; + +int bfoo() { return 4; } + +int z; +const int C1 = 1; +const int C2 = 2; +void test_linear_colons() +{ + int B = 0; + +#pragma omp target teams distribute simd linear(B:bfoo()) + for (int i = 0; i < 10; ++i) ; + +#pragma omp target teams distribute simd linear(B::ib:B:bfoo()) // expected-error {{unexpected ':' in nested name specifier; did you mean '::'}} + for (int i = 0; i < 10; ++i) ; + +#pragma omp target teams distribute simd linear(B:ib) // expected-error {{use of undeclared identifier 'ib'; did you mean 'B::ib'}} + for (int i = 0; i < 10; ++i) ; + +#pragma omp target teams distribute simd linear(z:B:ib) // expected-error {{unexpected ':' in nested name specifier; did you mean '::'?}} + for (int i = 0; i < 10; ++i) ; + +#pragma omp target teams distribute simd linear(B:B::bfoo()) + for (int i = 0; i < 10; ++i) ; + +#pragma omp target teams distribute simd linear(X::x : ::z) + for (int i = 0; i < 10; ++i) ; + +#pragma omp target teams distribute simd linear(B,::z, X::x) + for (int i = 0; i < 10; ++i) ; + +#pragma omp target teams distribute simd linear(::z) + for (int i = 0; i < 10; ++i) ; + +#pragma omp target teams distribute simd linear(B::bfoo()) // expected-error {{expected variable name}} + for (int i = 0; i < 10; ++i) ; + +#pragma omp target teams distribute simd linear(B::ib,B:C1+C2) + for (int i = 0; i < 10; ++i) ; +} + +template<int L, class T, class N> T test_template(T* arr, N num) { + N i; + T sum = (T)0; + T ind2 = - num * L; // expected-note {{'ind2' defined here}} + +#pragma omp target teams distribute simd linear(ind2:L) // expected-error {{argument of a linear clause should be of integral or pointer type}} + for (i = 0; i < num; ++i) { + T cur = arr[(int)ind2]; + ind2 += L; + sum += cur; + } + return T(); +} + +template<int LEN> int test_warn() { + int ind2 = 0; + #pragma omp target teams distribute simd linear(ind2:LEN) // expected-warning {{zero linear step (ind2 should probably be const)}} + for (int i = 0; i < 100; i++) { + ind2 += LEN; + } + return ind2; +} + +struct S1; // expected-note 2 {{declared here}} expected-note 2 {{forward declaration of 'S1'}} +extern S1 a; +class S2 { + mutable int a; +public: + S2():a(0) { } +}; +const S2 b; // expected-note 2 {{'b' defined here}} +const S2 ba[5]; +class S3 { + int a; +public: + S3():a(0) { } +}; +const S3 ca[5]; +class S4 { + int a; + S4(); +public: + S4(int v):a(v) { } +}; +class S5 { + int a; + S5():a(0) {} +public: + S5(int v):a(v) { } +}; + +S3 h; +#pragma omp threadprivate(h) // expected-note 2 {{defined as threadprivate or thread local}} + +template<class I, class C> int foomain(I argc, C **argv) { + I e(4); + I g(5); + int i; + int &j = i; + +#pragma omp target teams distribute simd linear // expected-error {{expected '(' after 'linear'}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd linear ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd linear () // expected-error {{expected expression}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd linear (argc // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd linear (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd linear (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd linear (argc : 5) + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd linear (S1) // expected-error {{'S1' does not refer to a value}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd linear (a, b:B::ib) // expected-error {{linear variable with incomplete type 'S1'}} expected-error {{const-qualified variable cannot be linear}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd linear (argv[1]) // expected-error {{expected variable name}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd linear(e, g) + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd linear(h) // expected-error {{threadprivate or thread local variable cannot be linear}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd linear(i) + for (int k = 0; k < argc; ++k) ++k; + + #pragma omp parallel + { + int v = 0; + int i; + #pragma omp target teams distribute simd linear(v:i) + for (int k = 0; k < argc; ++k) { i = k; v += i; } + } + +#pragma omp target teams distribute simd linear(j) + for (int k = 0; k < argc; ++k) ++k; + + int v = 0; + +#pragma omp target teams distribute simd linear(v:j) + for (int k = 0; k < argc; ++k) { ++k; v += j; } + +#pragma omp target teams distribute simd linear(i) + for (int k = 0; k < argc; ++k) ++k; + return 0; +} + +namespace A { +double x; +#pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}} +} +namespace C { +using A::x; +} + +int main(int argc, char **argv) { + double darr[100]; + // expected-note@+1 {{in instantiation of function template specialization 'test_template<-4, double, int>' requested here}} + test_template<-4>(darr, 4); + // expected-note@+1 {{in instantiation of function template specialization 'test_warn<0>' requested here}} + test_warn<0>(); + + S4 e(4); // expected-note {{'e' defined here}} + S5 g(5); // expected-note {{'g' defined here}} + int i; + int &j = i; + +#pragma omp target teams distribute simd linear // expected-error {{expected '(' after 'linear'}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd linear ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd linear () // expected-error {{expected expression}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd linear (argc // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd linear (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd linear (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd linear (argc) + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd linear (S1) // expected-error {{'S1' does not refer to a value}} + for (int k = 0; k < argc; ++k) ++k; + + +#pragma omp target teams distribute simd linear (a, b) // expected-error {{linear variable with incomplete type 'S1'}} expected-error {{const-qualified variable cannot be linear}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd linear (argv[1]) // expected-error {{expected variable name}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd linear(e, g) // expected-error {{argument of a linear clause should be of integral or pointer type, not 'S4'}} expected-error {{argument of a linear clause should be of integral or pointer type, not 'S5'}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd linear(h, C::x) // expected-error 2 {{threadprivate or thread local variable cannot be linear}} + for (int k = 0; k < argc; ++k) ++k; + + #pragma omp parallel + { + int i; + #pragma omp target teams distribute simd linear(i) + for (int k = 0; k < argc; ++k) ++k; + + #pragma omp target teams distribute simd linear(i : 4) + for (int k = 0; k < argc; ++k) { ++k; i += 4; } + } + +#pragma omp target teams distribute simd linear(j) + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd linear(i) + for (int k = 0; k < argc; ++k) ++k; + + foomain<int,char>(argc,argv); // expected-note {{in instantiation of function template specialization 'foomain<int, char>' requested here}} + return 0; +} + diff --git a/test/OpenMP/target_teams_distribute_simd_loop_messages.cpp b/test/OpenMP/target_teams_distribute_simd_loop_messages.cpp new file mode 100644 index 000000000000..3ddabce5e8d7 --- /dev/null +++ b/test/OpenMP/target_teams_distribute_simd_loop_messages.cpp @@ -0,0 +1,627 @@ +// RUN: %clang_cc1 -fsyntax-only -fopenmp -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s + +class S { + int a; + S() : a(0) {} + +public: + S(int v) : a(v) {} + S(const S &s) : a(s.a) {} +}; + +static int sii; +// expected-note@+1 {{defined as threadprivate or thread local}} +#pragma omp threadprivate(sii) +static int globalii; + +int test_iteration_spaces() { + const int N = 100; + float a[N], b[N], c[N]; + int ii, jj, kk; + float fii; + double dii; +#pragma omp target teams distribute simd + for (int i = 0; i < 10; i += 1) { + c[i] = a[i] + b[i]; + } +#pragma omp target teams distribute simd + for (char i = 0; i < 10; i++) { + c[i] = a[i] + b[i]; + } +#pragma omp target teams distribute simd + for (char i = 0; i < 10; i += '\1') { + c[i] = a[i] + b[i]; + } +#pragma omp target teams distribute simd + for (long long i = 0; i < 10; i++) { + c[i] = a[i] + b[i]; + } +#pragma omp target teams distribute simd +// expected-error@+1 {{expression must have integral or unscoped enumeration type, not 'double'}} + for (long long i = 0; i < 10; i += 1.5) { + c[i] = a[i] + b[i]; + } +#pragma omp target teams distribute simd + for (long long i = 0; i < 'z'; i += 1u) { + c[i] = a[i] + b[i]; + } +#pragma omp target teams distribute simd +// expected-error@+1 {{variable must be of integer or random access iterator type}} + for (float fi = 0; fi < 10.0; fi++) { + c[(int)fi] = a[(int)fi] + b[(int)fi]; + } +#pragma omp target teams distribute simd +// expected-error@+1 {{variable must be of integer or random access iterator type}} + for (double fi = 0; fi < 10.0; fi++) { + c[(int)fi] = a[(int)fi] + b[(int)fi]; + } +#pragma omp target teams distribute simd +// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}} + for (int &ref = ii; ref < 10; ref++) { + } +#pragma omp target teams distribute simd +// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}} + for (int i; i < 10; i++) + c[i] = a[i]; + +#pragma omp target teams distribute simd +// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}} + for (int i = 0, j = 0; i < 10; ++i) + c[i] = a[i]; + +#pragma omp target teams distribute simd +// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}} + for (; ii < 10; ++ii) + c[ii] = a[ii]; + +#pragma omp target teams distribute simd +// expected-warning@+2 {{expression result unused}} +// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}} + for (ii + 1; ii < 10; ++ii) + c[ii] = a[ii]; + +#pragma omp target teams distribute simd +// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}} + for (c[ii] = 0; ii < 10; ++ii) + c[ii] = a[ii]; + +#pragma omp target teams distribute simd +// Ok to skip parenthesises. + for (((ii)) = 0; ii < 10; ++ii) + c[ii] = a[ii]; + +#pragma omp target teams distribute simd +// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}} + for (int i = 0; i; i++) + c[i] = a[i]; + +#pragma omp target teams distribute simd +// expected-error@+2 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}} +// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'i'}} + for (int i = 0; jj < kk; ii++) + c[i] = a[i]; + +#pragma omp target teams distribute simd +// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}} + for (int i = 0; !!i; i++) + c[i] = a[i]; + +#pragma omp target teams distribute simd +// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}} + for (int i = 0; i != 1; i++) + c[i] = a[i]; + +#pragma omp target teams distribute simd +// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}} + for (int i = 0;; i++) + c[i] = a[i]; + +// Ok. +#pragma omp target teams distribute simd + for (int i = 11; i > 10; i--) + c[i] = a[i]; + +// Ok. +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) + c[i] = a[i]; + +// Ok. +#pragma omp target teams distribute simd + for (ii = 0; ii < 10; ++ii) + c[ii] = a[ii]; + +#pragma omp target teams distribute simd +// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}} + for (ii = 0; ii < 10; ++jj) + c[ii] = a[jj]; + +#pragma omp target teams distribute simd +// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}} + for (ii = 0; ii < 10; ++++ii) + c[ii] = a[ii]; + +// Ok but undefined behavior (in general, cannot check that incr +// is really loop-invariant). +#pragma omp target teams distribute simd + for (ii = 0; ii < 10; ii = ii + ii) + c[ii] = a[ii]; + +#pragma omp target teams distribute simd +// expected-error@+1 {{expression must have integral or unscoped enumeration type, not 'float'}} + for (ii = 0; ii < 10; ii = ii + 1.0f) + c[ii] = a[ii]; + +// Ok - step was converted to integer type. +#pragma omp target teams distribute simd + for (ii = 0; ii < 10; ii = ii + (int)1.1f) + c[ii] = a[ii]; + +#pragma omp target teams distribute simd +// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}} + for (ii = 0; ii < 10; jj = ii + 2) + c[ii] = a[ii]; + +#pragma omp target teams distribute simd +// expected-warning@+2 {{relational comparison result unused}} +// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}} + for (ii = 0; ii<10; jj> kk + 2) + c[ii] = a[ii]; + +#pragma omp target teams distribute simd +// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}} + for (ii = 0; ii < 10;) + c[ii] = a[ii]; + +#pragma omp target teams distribute simd +// expected-warning@+2 {{expression result unused}} +// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}} + for (ii = 0; ii < 10; !ii) + c[ii] = a[ii]; + +#pragma omp target teams distribute simd +// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}} + for (ii = 0; ii < 10; ii ? ++ii : ++jj) + c[ii] = a[ii]; + +#pragma omp target teams distribute simd +// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}} + for (ii = 0; ii < 10; ii = ii < 10) + c[ii] = a[ii]; + +#pragma omp target teams distribute simd +// expected-note@+2 {{loop step is expected to be positive due to this condition}} +// expected-error@+1 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}} + for (ii = 0; ii < 10; ii = ii + 0) + c[ii] = a[ii]; + +#pragma omp target teams distribute simd +// expected-note@+2 {{loop step is expected to be positive due to this condition}} +// expected-error@+1 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}} + for (ii = 0; ii < 10; ii = ii + (int)(0.8 - 0.45)) + c[ii] = a[ii]; + +#pragma omp target teams distribute simd +// expected-note@+2 {{loop step is expected to be positive due to this condition}} +// expected-error@+1 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}} + for (ii = 0; (ii) < 10; ii -= 25) + c[ii] = a[ii]; + +#pragma omp target teams distribute simd +// expected-note@+2 {{loop step is expected to be positive due to this condition}} +// expected-error@+1 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}} + for (ii = 0; (ii < 10); ii -= 0) + c[ii] = a[ii]; + +#pragma omp target teams distribute simd +// expected-note@+2 {{loop step is expected to be negative due to this condition}} +// expected-error@+1 {{increment expression must cause 'ii' to decrease on each iteration of OpenMP for loop}} + for (ii = 0; ii > 10; (ii += 0)) + c[ii] = a[ii]; + +#pragma omp target teams distribute simd +// expected-note@+2 {{loop step is expected to be positive due to this condition}} +// expected-error@+1 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}} + for (ii = 0; ii < 10; (ii) = (1 - 1) + (ii)) + c[ii] = a[ii]; + +#pragma omp target teams distribute simd +// expected-note@+2 {{loop step is expected to be negative due to this condition}} +// expected-error@+1 {{increment expression must cause 'ii' to decrease on each iteration of OpenMP for loop}} + for ((ii = 0); ii > 10; (ii -= 0)) + c[ii] = a[ii]; + +#pragma omp target teams distribute simd +// expected-note@+2 {{loop step is expected to be positive due to this condition}} +// expected-error@+1 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}} + for (ii = 0; (ii < 10); (ii -= 0)) + c[ii] = a[ii]; + +#pragma omp target teams distribute simd firstprivate(ii) // expected-note {{defined as firstprivate}} +// expected-error@+1 {{loop iteration variable in the associated loop of 'omp target teams distribute simd' directive may not be firstprivate, predetermined as linear}} + for (ii = 0; ii < 10; ii++) + c[ii] = a[ii]; + +#pragma omp target teams distribute simd private(ii) // expected-note {{defined as private}} +// expected-error@+1 {{loop iteration variable in the associated loop of 'omp target teams distribute simd' directive may not be private, predetermined as linear}} + for (ii = 0; ii < 10; ii++) + c[ii] = a[ii]; + +#pragma omp target teams distribute simd lastprivate(ii) // expected-note {{defined as lastprivate}} +// expected-error@+1 {{loop iteration variable in the associated loop of 'omp target teams distribute simd' directive may not be lastprivate, predetermined as linear}} + for (ii = 0; ii < 10; ii++) + c[ii] = a[ii]; + +#pragma omp target teams distribute simd +// expected-error@+1 {{loop iteration variable in the associated loop of 'omp target teams distribute simd' directive may not be threadprivate or thread local, predetermined as linear}} + for (sii = 0; sii < 10; sii++) + c[sii] = a[sii]; + + { +#pragma omp target teams distribute simd collapse(2) + for (ii = 0; ii < 10; ii += 1) + for (globalii = 0; globalii < 10; globalii += 1) + c[globalii] += a[globalii] + ii; + } + +#pragma omp target teams distribute simd +// expected-error@+1 {{statement after '#pragma omp target teams distribute simd' must be a for loop}} + for (auto &item : a) { + item = item + 1; + } + +#pragma omp target teams distribute simd +// expected-note@+2 {{loop step is expected to be positive due to this condition}} +// expected-error@+1 {{increment expression must cause 'i' to increase on each iteration of OpenMP for loop}} + for (unsigned i = 9; i < 10; i--) { + c[i] = a[i] + b[i]; + } + + int(*lb)[4] = nullptr; +#pragma omp target teams distribute simd + for (int(*p)[4] = lb; p < lb + 8; ++p) { + } + +#pragma omp target teams distribute simd +// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}} + for (int a{0}; a < 10; ++a) { + } + + return 0; +} + +// Iterators allowed in openmp for-loops. +namespace std { +struct random_access_iterator_tag {}; +template <class Iter> +struct iterator_traits { + typedef typename Iter::difference_type difference_type; + typedef typename Iter::iterator_category iterator_category; +}; +template <class Iter> +typename iterator_traits<Iter>::difference_type +distance(Iter first, Iter last) { return first - last; } +} +class Iter0 { +public: + Iter0() {} + Iter0(const Iter0 &) {} + Iter0 operator++() { return *this; } + Iter0 operator--() { return *this; } + bool operator<(Iter0 a) { return true; } +}; +// expected-note@+2 {{candidate function not viable: no known conversion from 'GoodIter' to 'Iter0' for 1st argument}} +// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'Iter0' for 1st argument}} +int operator-(Iter0 a, Iter0 b) { return 0; } +class Iter1 { +public: + Iter1(float f = 0.0f, double d = 0.0) {} + Iter1(const Iter1 &) {} + Iter1 operator++() { return *this; } + Iter1 operator--() { return *this; } + bool operator<(Iter1 a) { return true; } + bool operator>=(Iter1 a) { return false; } +}; +class GoodIter { +public: + GoodIter() {} + GoodIter(const GoodIter &) {} + GoodIter(int fst, int snd) {} + GoodIter &operator=(const GoodIter &that) { return *this; } + GoodIter &operator=(const Iter0 &that) { return *this; } + GoodIter &operator+=(int x) { return *this; } + explicit GoodIter(void *) {} + GoodIter operator++() { return *this; } + GoodIter operator--() { return *this; } + bool operator!() { return true; } + bool operator<(GoodIter a) { return true; } + bool operator<=(GoodIter a) { return true; } + bool operator>=(GoodIter a) { return false; } + typedef int difference_type; + typedef std::random_access_iterator_tag iterator_category; +}; +// expected-note@+2 {{candidate function not viable: no known conversion from 'const Iter0' to 'GoodIter' for 2nd argument}} +// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'GoodIter' for 1st argument}} +int operator-(GoodIter a, GoodIter b) { return 0; } +// expected-note@+1 3 {{candidate function not viable: requires single argument 'a', but 2 arguments were provided}} +GoodIter operator-(GoodIter a) { return a; } +// expected-note@+2 {{candidate function not viable: no known conversion from 'const Iter0' to 'int' for 2nd argument}} +// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'GoodIter' for 1st argument}} +GoodIter operator-(GoodIter a, int v) { return GoodIter(); } +// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter0' to 'GoodIter' for 1st argument}} +GoodIter operator+(GoodIter a, int v) { return GoodIter(); } +// expected-note@+2 {{candidate function not viable: no known conversion from 'GoodIter' to 'int' for 1st argument}} +// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'int' for 1st argument}} +GoodIter operator-(int v, GoodIter a) { return GoodIter(); } +// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter0' to 'int' for 1st argument}} +GoodIter operator+(int v, GoodIter a) { return GoodIter(); } + +int test_with_random_access_iterator() { + GoodIter begin, end; + Iter0 begin0, end0; +#pragma omp target teams distribute simd + for (GoodIter I = begin; I < end; ++I) + ++I; +#pragma omp target teams distribute simd +// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}} + for (GoodIter &I = begin; I < end; ++I) + ++I; +#pragma omp target teams distribute simd + for (GoodIter I = begin; I >= end; --I) + ++I; +#pragma omp target teams distribute simd +// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}} + for (GoodIter I(begin); I < end; ++I) + ++I; +#pragma omp target teams distribute simd +// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}} + for (GoodIter I(nullptr); I < end; ++I) + ++I; +#pragma omp target teams distribute simd +// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}} + for (GoodIter I(0); I < end; ++I) + ++I; +#pragma omp target teams distribute simd +// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}} + for (GoodIter I(1, 2); I < end; ++I) + ++I; +#pragma omp target teams distribute simd + for (begin = GoodIter(0); begin < end; ++begin) + ++begin; +#pragma omp target teams distribute simd +// expected-error@+2 {{invalid operands to binary expression ('GoodIter' and 'const Iter0')}} +// expected-error@+1 {{could not calculate number of iterations calling 'operator-' with upper and lower loop bounds}} + for (begin = begin0; begin < end; ++begin) + ++begin; +#pragma omp target teams distribute simd +// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}} + for (++begin; begin < end; ++begin) + ++begin; +#pragma omp target teams distribute simd + for (begin = end; begin < end; ++begin) + ++begin; +#pragma omp target teams distribute simd +// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'I'}} + for (GoodIter I = begin; I - I; ++I) + ++I; +#pragma omp target teams distribute simd +// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'I'}} + for (GoodIter I = begin; begin < end; ++I) + ++I; +#pragma omp target teams distribute simd +// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'I'}} + for (GoodIter I = begin; !I; ++I) + ++I; +#pragma omp target teams distribute simd +// expected-note@+2 {{loop step is expected to be negative due to this condition}} +// expected-error@+1 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}} + for (GoodIter I = begin; I >= end; I = I + 1) + ++I; +#pragma omp target teams distribute simd + for (GoodIter I = begin; I >= end; I = I - 1) + ++I; +#pragma omp target teams distribute simd +// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'I'}} + for (GoodIter I = begin; I >= end; I = -I) + ++I; +#pragma omp target teams distribute simd +// expected-note@+2 {{loop step is expected to be negative due to this condition}} +// expected-error@+1 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}} + for (GoodIter I = begin; I >= end; I = 2 + I) + ++I; +#pragma omp target teams distribute simd +// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'I'}} + for (GoodIter I = begin; I >= end; I = 2 - I) + ++I; +#pragma omp target teams distribute simd +// expected-error@+1 {{invalid operands to binary expression ('Iter0' and 'int')}} + for (Iter0 I = begin0; I < end0; ++I) + ++I; +#pragma omp target teams distribute simd +// Initializer is constructor without params. +// expected-error@+2 {{invalid operands to binary expression ('Iter0' and 'int')}} +// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}} + for (Iter0 I; I < end0; ++I) + ++I; + Iter1 begin1, end1; +#pragma omp target teams distribute simd +// expected-error@+2 {{invalid operands to binary expression ('Iter1' and 'Iter1')}} +// expected-error@+1 {{could not calculate number of iterations calling 'operator-' with upper and lower loop bounds}} + for (Iter1 I = begin1; I < end1; ++I) + ++I; +#pragma omp target teams distribute simd +// expected-note@+2 {{loop step is expected to be negative due to this condition}} +// expected-error@+1 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}} + for (Iter1 I = begin1; I >= end1; ++I) + ++I; +#pragma omp target teams distribute simd +// expected-error@+4 {{invalid operands to binary expression ('Iter1' and 'float')}} +// expected-error@+3 {{could not calculate number of iterations calling 'operator-' with upper and lower loop bounds}} +// Initializer is constructor with all default params. +// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}} + for (Iter1 I; I < end1; ++I) { + } + return 0; +} + +template <typename IT, int ST> +class TC { +public: + int dotest_lt(IT begin, IT end) { +#pragma omp target teams distribute simd +// expected-note@+2 {{loop step is expected to be positive due to this condition}} +// expected-error@+1 {{increment expression must cause 'I' to increase on each iteration of OpenMP for loop}} + for (IT I = begin; I < end; I = I + ST) { + ++I; + } +#pragma omp target teams distribute simd +// expected-note@+2 {{loop step is expected to be positive due to this condition}} +// expected-error@+1 {{increment expression must cause 'I' to increase on each iteration of OpenMP for loop}} + for (IT I = begin; I <= end; I += ST) { + ++I; + } +#pragma omp target teams distribute simd + for (IT I = begin; I < end; ++I) { + ++I; + } + } + + static IT step() { + return IT(ST); + } +}; +template <typename IT, int ST = 0> +int dotest_gt(IT begin, IT end) { +#pragma omp target teams distribute simd +// expected-note@+2 2 {{loop step is expected to be negative due to this condition}} +// expected-error@+1 2 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}} + for (IT I = begin; I >= end; I = I + ST) { + ++I; + } +#pragma omp target teams distribute simd +// expected-note@+2 2 {{loop step is expected to be negative due to this condition}} +// expected-error@+1 2 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}} + for (IT I = begin; I >= end; I += ST) { + ++I; + } + +#pragma omp target teams distribute simd +// expected-note@+2 {{loop step is expected to be negative due to this condition}} +// expected-error@+1 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}} + for (IT I = begin; I >= end; ++I) { + ++I; + } + +#pragma omp target teams distribute simd + for (IT I = begin; I < end; I += TC<int, ST>::step()) { + ++I; + } +} + +void test_with_template() { + GoodIter begin, end; + TC<GoodIter, 100> t1; + TC<GoodIter, -100> t2; + t1.dotest_lt(begin, end); + t2.dotest_lt(begin, end); // expected-note {{in instantiation of member function 'TC<GoodIter, -100>::dotest_lt' requested here}} + dotest_gt(begin, end); // expected-note {{in instantiation of function template specialization 'dotest_gt<GoodIter, 0>' requested here}} + dotest_gt<unsigned, -10>(0, 100); // expected-note {{in instantiation of function template specialization 'dotest_gt<unsigned int, -10>' requested here}} +} + +void test_loop_break() { + const int N = 100; + float a[N], b[N], c[N]; +#pragma omp target teams distribute simd + for (int i = 0; i < 10; i++) { + c[i] = a[i] + b[i]; + for (int j = 0; j < 10; ++j) { + if (a[i] > b[j]) + break; // OK in nested loop + } + switch (i) { + case 1: + b[i]++; + break; + default: + break; + } + if (c[i] > 10) + break; // expected-error {{'break' statement cannot be used in OpenMP for loop}} + + if (c[i] > 11) + break; // expected-error {{'break' statement cannot be used in OpenMP for loop}} + } + +#pragma omp target teams distribute simd + for (int i = 0; i < 10; i++) { + for (int j = 0; j < 10; j++) { + c[i] = a[i] + b[i]; + if (c[i] > 10) { + if (c[i] < 20) { + break; // OK + } + } + } + } +} + +void test_loop_eh() { + const int N = 100; + float a[N], b[N], c[N]; +#pragma omp target teams distribute simd + for (int i = 0; i < 10; i++) { + c[i] = a[i] + b[i]; + try { // expected-error {{'try' statement cannot be used in OpenMP simd region}} + for (int j = 0; j < 10; ++j) { + if (a[i] > b[j]) + throw a[i]; // expected-error {{throw' statement cannot be used in OpenMP simd region}} + } + throw a[i]; // expected-error {{throw' statement cannot be used in OpenMP simd region}} + } catch (float f) { + if (f > 0.1) + throw a[i]; // expected-error {{throw' statement cannot be used in OpenMP simd region}} + return; // expected-error {{cannot return from OpenMP region}} + } + switch (i) { + case 1: + b[i]++; + break; + default: + break; + } + for (int j = 0; j < 10; j++) { + if (c[i] > 10) + throw c[i]; // expected-error {{throw' statement cannot be used in OpenMP simd region}} + } + } + if (c[9] > 10) + throw c[9]; // OK + +#pragma omp target teams distribute simd + for (int i = 0; i < 10; ++i) { + struct S { + void g() { throw 0; } + }; + } +} + +void test_loop_firstprivate_lastprivate() { + S s(4); +#pragma omp target teams distribute simd lastprivate(s) firstprivate(s) + for (int i = 0; i < 16; ++i) + ; +} + +void test_ordered() { +#pragma omp target teams distribute simd ordered // expected-error {{unexpected OpenMP clause 'ordered' in directive '#pragma omp target teams distribute simd'}} + for (int i = 0; i < 16; ++i) + ; +} + +void test_nowait() { +// expected-error@+1 {{directive '#pragma omp target teams distribute simd' cannot contain more than one 'nowait' clause}} +#pragma omp target teams distribute simd nowait nowait + for (int i = 0; i < 16; ++i) + ; +} + diff --git a/test/OpenMP/target_teams_distribute_simd_map_messages.cpp b/test/OpenMP/target_teams_distribute_simd_map_messages.cpp new file mode 100644 index 000000000000..414f6f83debb --- /dev/null +++ b/test/OpenMP/target_teams_distribute_simd_map_messages.cpp @@ -0,0 +1,281 @@ +// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s + +void foo() { +} + +bool foobool(int argc) { + return argc; +} + +struct S1; // expected-note 2 {{declared here}} +extern S1 a; +class S2 { + mutable int a; +public: + S2():a(0) { } + S2(S2 &s2):a(s2.a) { } + static float S2s; // expected-note 4 {{mappable type cannot contain static members}} + static const float S2sc; // expected-note 4 {{mappable type cannot contain static members}} +}; +const float S2::S2sc = 0; +const S2 b; +const S2 ba[5]; +class S3 { + int a; +public: + S3():a(0) { } + S3(S3 &s3):a(s3.a) { } +}; +const S3 c; +const S3 ca[5]; +extern const int f; +class S4 { + int a; + S4(); + S4(const S4 &s4); +public: + S4(int v):a(v) { } +}; +class S5 { + int a; + S5():a(0) {} + S5(const S5 &s5):a(s5.a) { } +public: + S5(int v):a(v) { } +}; + +S3 h; +#pragma omp threadprivate(h) // expected-note 2 {{defined as threadprivate or thread local}} + +typedef int from; + +template <typename T, int I> // expected-note {{declared here}} +T tmain(T argc) { + const T d = 5; + const T da[5] = { 0 }; + S4 e(4); + S5 g(5); + T i, t[20]; + T &j = i; + T *k = &j; + T x; + T y; + T to, tofrom, always; + const T (&l)[5] = da; + + +#pragma omp target teams distribute simd map // expected-error {{expected '(' after 'map'}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map() // expected-error {{expected expression}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(alloc) // expected-error {{use of undeclared identifier 'alloc'}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(to argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected ',' or ')' in 'map' clause}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(to:) // expected-error {{expected expression}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(from: argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(x: y) // expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(l[-1:]) // expected-error 2 {{array section must be a subset of the original array}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(l[:-1]) // expected-error 2 {{section length is evaluated to a negative value -1}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(x) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(tofrom: t[:I]) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(T: a) // expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}} expected-error {{incomplete type 'S1' where a complete type is required}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(T) // expected-error {{'T' does not refer to a value}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(I) // expected-error 2 {{expected expression containing only member accesses and/or array sections based on named variables}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(S2::S2s) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(S2::S2sc) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(x) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(to: x) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(to: to) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(to) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(to, x) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(to x) // expected-error {{expected ',' or ')' in 'map' clause}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(tofrom: argc > 0 ? x : y) // expected-error 2 {{expected expression containing only member accesses and/or array sections based on named variables}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(argc) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(S1) // expected-error {{'S1' does not refer to a value}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(a, b, c, d, f) // expected-error {{incomplete type 'S1' where a complete type is required}} expected-error 2 {{type 'S2' is not mappable to target}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(ba) // expected-error 2 {{type 'S2' is not mappable to target}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(ca) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(da) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(S2::S2s) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(S2::S2sc) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(e, g) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(h) // expected-error {{threadprivate variables are not allowed in 'map' clause}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(k), map(k) // expected-error 2 {{variable already marked as mapped in current construct}} expected-note 2 {{used here}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(k), map(k[:5]) // expected-error 2 {{pointer cannot be mapped along with a section derived from itself}} expected-note 2 {{used here}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(da) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(da[:4]) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target data map(k, j, l) // expected-note 2 {{used here}} +#pragma omp target teams distribute simd map(k[:4]) // expected-error 2 {{pointer cannot be mapped along with a section derived from itself}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(j) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(l) map(l[:5]) // expected-error 2 {{variable already marked as mapped in current construct}} expected-note 2 {{used here}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target data map(k[:4], j, l[:5]) // expected-note 2 {{used here}} +{ +#pragma omp target teams distribute simd map(k) // expected-error 2 {{pointer cannot be mapped along with a section derived from itself}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(j) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(l) + for (i = 0; i < argc; ++i) foo(); +} + +#pragma omp target teams distribute simd map(always, tofrom: x) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(always: x) // expected-error {{missing map type}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always'}} expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(always, tofrom: always, tofrom, x) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(tofrom j) // expected-error {{expected ',' or ')' in 'map' clause}} + for (i = 0; i < argc; ++i) foo(); + + return 0; +} + +int main(int argc, char **argv) { + const int d = 5; + const int da[5] = { 0 }; + S4 e(4); + S5 g(5); + int i; + int &j = i; + int *k = &j; + int x; + int y; + int to, tofrom, always; + const int (&l)[5] = da; + +#pragma omp target teams distribute simd map // expected-error {{expected '(' after 'map'}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map() // expected-error {{expected expression}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(alloc) // expected-error {{use of undeclared identifier 'alloc'}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(to argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected ',' or ')' in 'map' clause}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(to:) // expected-error {{expected expression}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(from: argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(x: y) // expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(l[-1:]) // expected-error {{array section must be a subset of the original array}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(l[:-1]) // expected-error {{section length is evaluated to a negative value -1}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(x) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(to: x) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(to: to) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(to) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(to, x) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(to x) // expected-error {{expected ',' or ')' in 'map' clause}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(tofrom: argc > 0 ? argv[1] : argv[2]) // expected-error {{expected expression containing only member accesses and/or array sections based on named variables}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(argc) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(S1) // expected-error {{'S1' does not refer to a value}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(a, b, c, d, f) // expected-error {{incomplete type 'S1' where a complete type is required}} expected-error 2 {{type 'S2' is not mappable to target}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(argv[1]) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(ba) // expected-error 2 {{type 'S2' is not mappable to target}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(ca) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(da) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(S2::S2s) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(S2::S2sc) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(e, g) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(h) // expected-error {{threadprivate variables are not allowed in 'map' clause}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(k), map(k) // expected-error {{variable already marked as mapped in current construct}} expected-note {{used here}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(k), map(k[:5]) // expected-error {{pointer cannot be mapped along with a section derived from itself}} expected-note {{used here}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(da) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(da[:4]) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target data map(k, j, l) // expected-note {{used here}} +#pragma omp target teams distribute simd map(k[:4]) // expected-error {{pointer cannot be mapped along with a section derived from itself}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(j) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(l) map(l[:5]) // expected-error 1 {{variable already marked as mapped in current construct}} expected-note 1 {{used here}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target data map(k[:4], j, l[:5]) // expected-note {{used here}} +{ +#pragma omp target teams distribute simd map(k) // expected-error {{pointer cannot be mapped along with a section derived from itself}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(j) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(l) + for (i = 0; i < argc; ++i) foo(); +} + +#pragma omp target teams distribute simd map(always, tofrom: x) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(always: x) // expected-error {{missing map type}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always'}} expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(always, tofrom: always, tofrom, x) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd map(tofrom j) // expected-error {{expected ',' or ')' in 'map' clause}} + for (i = 0; i < argc; ++i) foo(); + + return tmain<int, 3>(argc)+tmain<from, 4>(argc); // expected-note {{in instantiation of function template specialization 'tmain<int, 3>' requested here}} expected-note {{in instantiation of function template specialization 'tmain<int, 4>' requested here}} +} + diff --git a/test/OpenMP/target_teams_distribute_simd_messages.cpp b/test/OpenMP/target_teams_distribute_simd_messages.cpp new file mode 100644 index 000000000000..aa82c947010f --- /dev/null +++ b/test/OpenMP/target_teams_distribute_simd_messages.cpp @@ -0,0 +1,93 @@ +// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s + +void foo() { +} + +static int pvt; +#pragma omp threadprivate(pvt) + +#pragma omp target teams distribute simd // expected-error {{unexpected OpenMP directive '#pragma omp target teams distribute simd'}} + +int main(int argc, char **argv) { +#pragma omp target teams distribute simd { // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute simd' are ignored}} + for (int i = 0; i < argc; ++i) + foo(); +#pragma omp target teams distribute simd ( // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute simd' are ignored}} + for (int i = 0; i < argc; ++i) + foo(); +#pragma omp target teams distribute simd[ // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute simd' are ignored}} + for (int i = 0; i < argc; ++i) + foo(); +#pragma omp target teams distribute simd] // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute simd' are ignored}} + for (int i = 0; i < argc; ++i) + foo(); +#pragma omp target teams distribute simd) // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute simd' are ignored}} + for (int i = 0; i < argc; ++i) + foo(); +#pragma omp target teams distribute simd } // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute simd' are ignored}} + for (int i = 0; i < argc; ++i) + foo(); +#pragma omp target teams distribute simd + for (int i = 0; i < argc; ++i) + foo(); +// expected-warning@+1 {{extra tokens at the end of '#pragma omp target teams distribute simd' are ignored}} +#pragma omp target teams distribute simd unknown() + for (int i = 0; i < argc; ++i) + foo(); +L1: + for (int i = 0; i < argc; ++i) + foo(); +#pragma omp target teams distribute simd + for (int i = 0; i < argc; ++i) + foo(); +#pragma omp target teams distribute simd + for (int i = 0; i < argc; ++i) { + goto L1; // expected-error {{use of undeclared label 'L1'}} + argc++; + } + + for (int i = 0; i < 10; ++i) { + switch (argc) { + case (0): +#pragma omp target teams distribute simd + for (int i = 0; i < argc; ++i) { + foo(); + break; // expected-error {{'break' statement cannot be used in OpenMP for loop}} + continue; + } + default: + break; + } + } +// expected-error@+1 {{unexpected OpenMP clause 'default' in directive '#pragma omp target teams distribute simd'}} +#pragma omp target teams distribute simd default(none) + for (int i = 0; i < 10; ++i) + ++argc; // expected-error {{ariable 'argc' must have explicitly specified data sharing attributes}} + + goto L2; // expected-error {{use of undeclared label 'L2'}} +#pragma omp target teams distribute simd + for (int i = 0; i < argc; ++i) + L2: + foo(); +#pragma omp target teams distribute simd + for (int i = 0; i < argc; ++i) { + return 1; // expected-error {{cannot return from OpenMP region}} + } + + [[]] // expected-error {{an attribute list cannot appear here}} +#pragma omp target teams distribute simd + for (int n = 0; n < 100; ++n) { + } + +#pragma omp target teams distribute simd copyin(pvt) // expected-error {{unexpected OpenMP clause 'copyin' in directive '#pragma omp target teams distribute simd'}} + for (int n = 0; n < 100; ++n) {} + + return 0; +} + +void test_ordered() { +#pragma omp target teams distribute simd ordered // expected-error {{unexpected OpenMP clause 'ordered' in directive '#pragma omp target teams distribute simd'}} + for (int i = 0; i < 16; ++i) + ; +} + diff --git a/test/OpenMP/target_teams_distribute_simd_misc_messages.c b/test/OpenMP/target_teams_distribute_simd_misc_messages.c new file mode 100644 index 000000000000..c76fdea4fcf1 --- /dev/null +++ b/test/OpenMP/target_teams_distribute_simd_misc_messages.c @@ -0,0 +1,312 @@ +// RUN: %clang_cc1 -fsyntax-only -fopenmp -verify %s + +// expected-error@+1 {{unexpected OpenMP directive '#pragma omp target teams distribute simd'}} +#pragma omp target teams distribute simd + +// expected-error@+1 {{unexpected OpenMP directive '#pragma omp target teams distribute simd'}} +#pragma omp target teams distribute simd foo + +void test_no_clause() { + int i; +#pragma omp target teams distribute simd + for (i = 0; i < 16; ++i) + ; + +// expected-error@+2 {{statement after '#pragma omp target teams distribute simd' must be a for loop}} +#pragma omp target teams distribute simd + ++i; +} + +void test_branch_protected_scope() { + int i = 0; +L1: + ++i; + + int x[24]; + +#pragma omp target teams distribute simd + for (i = 0; i < 16; ++i) { + if (i == 5) + goto L1; // expected-error {{use of undeclared label 'L1'}} + else if (i == 6) + return; // expected-error {{cannot return from OpenMP region}} + else if (i == 7) + goto L2; + else if (i == 8) { + L2: + x[i]++; + } + } + + if (x[0] == 0) + goto L2; // expected-error {{use of undeclared label 'L2'}} + else if (x[1] == 1) + goto L1; +} + +void test_invalid_clause() { + int i; +// expected-warning@+1 {{extra tokens at the end of '#pragma omp target teams distribute simd' are ignored}} +#pragma omp target teams distribute simd foo bar + for (i = 0; i < 16; ++i) + ; +} + +void test_non_identifiers() { + int i, x; + +// expected-warning@+1 {{extra tokens at the end of '#pragma omp target teams distribute simd' are ignored}} +#pragma omp target teams distribute simd; + for (i = 0; i < 16; ++i) + ; + +// expected-warning@+1 {{extra tokens at the end of '#pragma omp target teams distribute simd' are ignored}} +#pragma omp target teams distribute simd private(x); + for (i = 0; i < 16; ++i) + ; + +// expected-warning@+1 {{extra tokens at the end of '#pragma omp target teams distribute simd' are ignored}} +#pragma omp target teams distribute simd, private(x); + for (i = 0; i < 16; ++i) + ; +} + +extern int foo(); + +void test_collapse() { + int i; +// expected-error@+1 {{expected '('}} +#pragma omp target teams distribute simd collapse + for (i = 0; i < 16; ++i) + ; +// expected-error@+1 {{expected expression}} expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}} +#pragma omp target teams distribute simd collapse( + for (i = 0; i < 16; ++i) + ; +// expected-error@+1 {{expected expression}} +#pragma omp target teams distribute simd collapse() + for (i = 0; i < 16; ++i) + ; +// expected-error@+1 {{expected expression}} expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}} +#pragma omp target teams distribute simd collapse(, + for (i = 0; i < 16; ++i) + ; +// expected-error@+1 {{expected expression}} expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}} +#pragma omp target teams distribute simd collapse(, ) + for (i = 0; i < 16; ++i) + ; +// expected-warning@+2 {{extra tokens at the end of '#pragma omp target teams distribute simd' are ignored}} +// expected-error@+1 {{expected '('}} +#pragma omp target teams distribute simd collapse 4) + for (i = 0; i < 16; ++i) + ; +// expected-error@+2 {{expected ')'}} +// expected-note@+1 {{to match this '('}} expected-note@+1 {{as specified in 'collapse' clause}} +#pragma omp target teams distribute simd collapse(4 + for (i = 0; i < 16; ++i) + ; // expected-error {{expected 4 for loops after '#pragma omp target teams distribute simd', but found only 1}} +// expected-error@+2 {{expected ')'}} +// expected-note@+1 {{to match this '('}} expected-note@+1 {{as specified in 'collapse' clause}} +#pragma omp target teams distribute simd collapse(4, + for (i = 0; i < 16; ++i) + ; // expected-error {{expected 4 for loops after '#pragma omp target teams distribute simd', but found only 1}} +// expected-error@+2 {{expected ')'}} +// expected-note@+1 {{to match this '('}} expected-note@+1 {{as specified in 'collapse' clause}} +#pragma omp target teams distribute simd collapse(4, ) + for (i = 0; i < 16; ++i) + ; // expected-error {{expected 4 for loops after '#pragma omp target teams distribute simd', but found only 1}} +// expected-note@+1 {{as specified in 'collapse' clause}} +#pragma omp target teams distribute simd collapse(4) + for (i = 0; i < 16; ++i) + ; // expected-error {{expected 4 for loops after '#pragma omp target teams distribute simd', but found only 1}} +// expected-error@+2 {{expected ')'}} +// expected-note@+1 {{to match this '('}} expected-note@+1 {{as specified in 'collapse' clause}} +#pragma omp target teams distribute simd collapse(4 4) + for (i = 0; i < 16; ++i) + ; // expected-error {{expected 4 for loops after '#pragma omp target teams distribute simd', but found only 1}} +// expected-error@+2 {{expected ')'}} +// expected-note@+1 {{to match this '('}} expected-note@+1 {{as specified in 'collapse' clause}} +#pragma omp target teams distribute simd collapse(4, , 4) + for (i = 0; i < 16; ++i) + ; // expected-error {{expected 4 for loops after '#pragma omp target teams distribute simd', but found only 1}} +#pragma omp target teams distribute simd collapse(4) + for (int i1 = 0; i1 < 16; ++i1) + for (int i2 = 0; i2 < 16; ++i2) + for (int i3 = 0; i3 < 16; ++i3) + for (int i4 = 0; i4 < 16; ++i4) + foo(); +// expected-error@+2 {{expected ')'}} +// expected-note@+1 {{to match this '('}} expected-note@+1 {{as specified in 'collapse' clause}} +#pragma omp target teams distribute simd collapse(4, 8) + for (i = 0; i < 16; ++i) + ; // expected-error {{expected 4 for loops after '#pragma omp target teams distribute simd', but found only 1}} +// expected-error@+1 {{expression is not an integer constant expression}} +#pragma omp target teams distribute simd collapse(2.5) + for (i = 0; i < 16; ++i) + ; +// expected-error@+1 {{expression is not an integer constant expression}} +#pragma omp target teams distribute simd collapse(foo()) + for (i = 0; i < 16; ++i) + ; +// expected-error@+1 {{argument to 'collapse' clause must be a strictly positive integer value}} +#pragma omp target teams distribute simd collapse(-5) + for (i = 0; i < 16; ++i) + ; +// expected-error@+1 {{argument to 'collapse' clause must be a strictly positive integer value}} +#pragma omp target teams distribute simd collapse(0) + for (i = 0; i < 16; ++i) + ; +// expected-error@+1 {{argument to 'collapse' clause must be a strictly positive integer value}} +#pragma omp target teams distribute simd collapse(5 - 5) + for (i = 0; i < 16; ++i) + ; + +// expected-error@+4 {{OpenMP constructs may not be nested inside a simd region}} +#pragma omp target teams distribute simd collapse(2) firstprivate(i) + for (i = 0; i < 16; ++i) + for (int j = 0; j < 16; ++j) +#pragma omp parallel for reduction(+ : i, j) + for (int k = 0; k < 16; ++k) + i += j; +} + +void test_private() { + int i; +// expected-error@+2 {{expected expression}} +// expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}} +#pragma omp target teams distribute simd private( + for (i = 0; i < 16; ++i) + ; +// expected-error@+2 {{expected ')'}} expected-note@+2 {{to match this '('}} +// expected-error@+1 2 {{expected expression}} +#pragma omp target teams distribute simd private(, + for (i = 0; i < 16; ++i) + ; +// expected-error@+1 2 {{expected expression}} +#pragma omp target teams distribute simd private(, ) + for (i = 0; i < 16; ++i) + ; +// expected-error@+1 {{expected expression}} +#pragma omp target teams distribute simd private() + for (i = 0; i < 16; ++i) + ; +// expected-error@+1 {{expected expression}} +#pragma omp target teams distribute simd private(int) + for (i = 0; i < 16; ++i) + ; +// expected-error@+1 {{expected variable name}} +#pragma omp target teams distribute simd private(0) + for (i = 0; i < 16; ++i) + ; + + int x, y, z; +#pragma omp target teams distribute simd private(x) + for (i = 0; i < 16; ++i) + ; +#pragma omp target teams distribute simd private(x, y) + for (i = 0; i < 16; ++i) + ; +#pragma omp target teams distribute simd private(x, y, z) + for (i = 0; i < 16; ++i) { + x = y * i + z; + } +} + +void test_lastprivate() { + int i; +// expected-error@+2 {{expected ')'}} expected-note@+2 {{to match this '('}} +// expected-error@+1 {{expected expression}} +#pragma omp target teams distribute simd lastprivate( + for (i = 0; i < 16; ++i) + ; + +// expected-error@+2 {{expected ')'}} expected-note@+2 {{to match this '('}} +// expected-error@+1 2 {{expected expression}} +#pragma omp target teams distribute simd lastprivate(, + for (i = 0; i < 16; ++i) + ; +// expected-error@+1 2 {{expected expression}} +#pragma omp target teams distribute simd lastprivate(, ) + for (i = 0; i < 16; ++i) + ; +// expected-error@+1 {{expected expression}} +#pragma omp target teams distribute simd lastprivate() + for (i = 0; i < 16; ++i) + ; +// expected-error@+1 {{expected expression}} +#pragma omp target teams distribute simd lastprivate(int) + for (i = 0; i < 16; ++i) + ; +// expected-error@+1 {{expected variable name}} +#pragma omp target teams distribute simd lastprivate(0) + for (i = 0; i < 16; ++i) + ; + + int x, y, z; +#pragma omp target teams distribute simd lastprivate(x) + for (i = 0; i < 16; ++i) + ; +#pragma omp target teams distribute simd lastprivate(x, y) + for (i = 0; i < 16; ++i) + ; +#pragma omp target teams distribute simd lastprivate(x, y, z) + for (i = 0; i < 16; ++i) + ; +} + +void test_firstprivate() { + int i; +// expected-error@+2 {{expected ')'}} expected-note@+2 {{to match this '('}} +// expected-error@+1 {{expected expression}} +#pragma omp target teams distribute simd firstprivate( + for (i = 0; i < 16; ++i) + ; + +// expected-error@+2 {{expected ')'}} expected-note@+2 {{to match this '('}} +// expected-error@+1 2 {{expected expression}} +#pragma omp target teams distribute simd firstprivate(, + for (i = 0; i < 16; ++i) + ; +// expected-error@+1 2 {{expected expression}} +#pragma omp target teams distribute simd firstprivate(, ) + for (i = 0; i < 16; ++i) + ; +// expected-error@+1 {{expected expression}} +#pragma omp target teams distribute simd firstprivate() + for (i = 0; i < 16; ++i) + ; +// expected-error@+1 {{expected expression}} +#pragma omp target teams distribute simd firstprivate(int) + for (i = 0; i < 16; ++i) + ; +// expected-error@+1 {{expected variable name}} +#pragma omp target teams distribute simd firstprivate(0) + for (i = 0; i < 16; ++i) + ; + + int x, y, z; +#pragma omp target teams distribute simd lastprivate(x) firstprivate(x) + for (i = 0; i < 16; ++i) + ; +#pragma omp target teams distribute simd lastprivate(x, y) firstprivate(x, y) + for (i = 0; i < 16; ++i) + ; +#pragma omp target teams distribute simd lastprivate(x, y, z) firstprivate(x, y, z) + for (i = 0; i < 16; ++i) + ; +} + +void test_loop_messages() { + float a[100], b[100], c[100]; +// expected-error@+2 {{variable must be of integer or pointer type}} +#pragma omp target teams distribute simd + for (float fi = 0; fi < 10.0; fi++) { + c[(int)fi] = a[(int)fi] + b[(int)fi]; + } +// expected-error@+2 {{variable must be of integer or pointer type}} +#pragma omp target teams distribute simd + for (double fi = 0; fi < 10.0; fi++) { + c[(int)fi] = a[(int)fi] + b[(int)fi]; + } +} + diff --git a/test/OpenMP/target_teams_distribute_simd_nowait_messages.cpp b/test/OpenMP/target_teams_distribute_simd_nowait_messages.cpp new file mode 100644 index 000000000000..6c2c2a50ab55 --- /dev/null +++ b/test/OpenMP/target_teams_distribute_simd_nowait_messages.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -fopenmp %s + +void foo() { +} + +int main(int argc, char **argv) { + int i; +#pragma omp target teams distribute simd nowait( // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute simd' are ignored}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd nowait (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute simd' are ignored}} + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd nowait device (-10u) + for (i = 0; i < argc; ++i) foo(); +#pragma omp target teams distribute simd nowait (3.14) device (-10u) // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute simd' are ignored}} + for (i = 0; i < argc; ++i) foo(); + + return 0; +} diff --git a/test/OpenMP/target_teams_distribute_simd_num_teams_messages.cpp b/test/OpenMP/target_teams_distribute_simd_num_teams_messages.cpp new file mode 100644 index 000000000000..63926bcfcbe9 --- /dev/null +++ b/test/OpenMP/target_teams_distribute_simd_num_teams_messages.cpp @@ -0,0 +1,85 @@ +// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 100 -o - %s + +void foo() { +} + +bool foobool(int argc) { + return argc; +} + +struct S1; // expected-note 2 {{declared here}} + +template <typename T, int C> // expected-note {{declared here}} +T tmain(T argc) { + char **a; +#pragma omp target teams distribute simd num_teams(C) + for (int i=0; i<100; i++) foo(); +#pragma omp target teams distribute simd num_teams(T) // expected-error {{'T' does not refer to a value}} + for (int i=0; i<100; i++) foo(); +#pragma omp target teams distribute simd num_teams // expected-error {{expected '(' after 'num_teams'}} + for (int i=0; i<100; i++) foo(); +#pragma omp target teams distribute simd num_teams( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int i=0; i<100; i++) foo(); +#pragma omp target teams distribute simd num_teams() // expected-error {{expected expression}} + for (int i=0; i<100; i++) foo(); +#pragma omp target teams distribute simd num_teams(argc // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int i=0; i<100; i++) foo(); +#pragma omp target teams distribute simd num_teams(argc)) // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute simd' are ignored}} + for (int i=0; i<100; i++) foo(); +#pragma omp target teams distribute simd num_teams(argc > 0 ? a[1] : a[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} + for (int i=0; i<100; i++) foo(); +#pragma omp target teams distribute simd num_teams(argc + argc) + for (int i=0; i<100; i++) foo(); +#pragma omp target teams distribute simd num_teams(argc), num_teams (argc+1) // expected-error {{directive '#pragma omp target teams distribute simd' cannot contain more than one 'num_teams' clause}} + for (int i=0; i<100; i++) foo(); +#pragma omp target teams distribute simd num_teams(S1) // expected-error {{'S1' does not refer to a value}} + for (int i=0; i<100; i++) foo(); +#pragma omp target teams distribute simd num_teams(-2) // expected-error {{argument to 'num_teams' clause must be a strictly positive integer value}} + for (int i=0; i<100; i++) foo(); +#pragma omp target teams distribute simd num_teams(-10u) + for (int i=0; i<100; i++) foo(); +#pragma omp target teams distribute simd num_teams(3.14) // expected-error 2 {{expression must have integral or unscoped enumeration type, not 'double'}} + for (int i=0; i<100; i++) foo(); + + return 0; +} + +int main(int argc, char **argv) { +#pragma omp target teams distribute simd num_teams // expected-error {{expected '(' after 'num_teams'}} + for (int i=0; i<100; i++) foo(); + +#pragma omp target teams distribute simd num_teams ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int i=0; i<100; i++) foo(); + +#pragma omp target teams distribute simd num_teams () // expected-error {{expected expression}} + for (int i=0; i<100; i++) foo(); + +#pragma omp target teams distribute simd num_teams (argc // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int i=0; i<100; i++) foo(); + +#pragma omp target teams distribute simd num_teams (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute simd' are ignored}} + for (int i=0; i<100; i++) foo(); + +#pragma omp target teams distribute simd num_teams (argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} + for (int i=0; i<100; i++) foo(); + +#pragma omp target teams distribute simd num_teams (argc + argc) + for (int i=0; i<100; i++) foo(); + +#pragma omp target teams distribute simd num_teams (argc), num_teams (argc+1) // expected-error {{directive '#pragma omp target teams distribute simd' cannot contain more than one 'num_teams' clause}} + for (int i=0; i<100; i++) foo(); + +#pragma omp target teams distribute simd num_teams (S1) // expected-error {{'S1' does not refer to a value}} + for (int i=0; i<100; i++) foo(); + +#pragma omp target teams distribute simd num_teams (-2) // expected-error {{argument to 'num_teams' clause must be a strictly positive integer value}} + for (int i=0; i<100; i++) foo(); + +#pragma omp target teams distribute simd num_teams (-10u) + for (int i=0; i<100; i++) foo(); + +#pragma omp target teams distribute simd num_teams (3.14) // expected-error {{expression must have integral or unscoped enumeration type, not 'double'}} + for (int i=0; i<100; i++) foo(); + + return tmain<int, 10>(argc); // expected-note {{in instantiation of function template specialization 'tmain<int, 10>' requested here}} +} diff --git a/test/OpenMP/target_teams_distribute_simd_private_messages.cpp b/test/OpenMP/target_teams_distribute_simd_private_messages.cpp new file mode 100644 index 000000000000..3d351bdc7d82 --- /dev/null +++ b/test/OpenMP/target_teams_distribute_simd_private_messages.cpp @@ -0,0 +1,127 @@ +// RUN: %clang_cc1 -verify -fopenmp %s + +void foo() { +} + +bool foobool(int argc) { + return argc; +} + +struct S1; // expected-note {{declared here}} expected-note {{forward declaration of 'S1'}} +extern S1 a; +class S2 { + mutable int a; +public: + S2():a(0) { } + static float S2s; // expected-note {{predetermined as shared}} +}; +const S2 b; +const S2 ba[5]; +class S3 { + int a; +public: + S3():a(0) { } +}; +const S3 c; // expected-note {{predetermined as shared}} +const S3 ca[5]; // expected-note {{predetermined as shared}} +extern const int f; // expected-note {{predetermined as shared}} +class S4 { + int a; + S4(); // expected-note {{implicitly declared private here}} +public: + S4(int v):a(v) { } +}; +class S5 { + int a; + S5():a(0) {} // expected-note {{implicitly declared private here}} +public: + S5(int v):a(v) { } +}; + +S3 h; +#pragma omp threadprivate(h) // expected-note {{defined as threadprivate or thread local}} + + +int main(int argc, char **argv) { + const int d = 5; // expected-note {{predetermined as shared}} + const int da[5] = { 0 }; // expected-note {{predetermined as shared}} + S4 e(4); + S5 g(5); + int i; + int &j = i; + +#pragma omp target teams distribute simd private // expected-error {{expected '(' after 'private'}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd private ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd private () // expected-error {{expected expression}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd private (argc // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd private (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd private (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd private (argc) + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd private (S1) // expected-error {{'S1' does not refer to a value}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd private (a, b, c, d, f) // expected-error {{private variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be private}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd private (argv[1]) // expected-error {{expected variable name}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd private(ba) + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd private(ca) // expected-error {{shared variable cannot be private}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd private(da) // expected-error {{shared variable cannot be private}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd private(S2::S2s) // expected-error {{shared variable cannot be private}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd private(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd private(h) // expected-error {{threadprivate or thread local variable cannot be private}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd shared(i) + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd firstprivate(i), private(i) // expected-error {{firstprivate variable cannot be private}} expected-note {{defined as firstprivate}} + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd private(j) + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp target teams distribute simd reduction(+:i) + for (int k = 0; k < argc; ++k) ++k; + +#pragma omp distribute private(i) + for (int k = 0; k < 10; ++k) { + #pragma omp target teams distribute simd private(i) + for (int x = 0; x < 10; ++x) foo(); + } + +#pragma omp target teams distribute simd firstprivate(i) + for (int k = 0; k < 10; ++k) { + } + +#pragma omp target teams distribute simd private(j) map(j) // expected-error {{private variable cannot be in a map clause in '#pragma omp target teams distribute simd' directive}} expected-note {{defined as private}} + for (int k = 0; k < argc; ++k) ++k; + + return 0; +} diff --git a/test/OpenMP/target_teams_distribute_simd_reduction_messages.cpp b/test/OpenMP/target_teams_distribute_simd_reduction_messages.cpp new file mode 100644 index 000000000000..1c0283285aa5 --- /dev/null +++ b/test/OpenMP/target_teams_distribute_simd_reduction_messages.cpp @@ -0,0 +1,241 @@ +// RUN: %clang_cc1 -verify -fopenmp %s +// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s +// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s + +void foo() { +} + +bool foobool(int argc) { + return argc; +} + +struct S1; // expected-note {{declared here}} expected-note 4 {{forward declaration of 'S1'}} +extern S1 a; +class S2 { + mutable int a; + S2 &operator+(const S2 &arg) { return (*this); } // expected-note 3 {{implicitly declared private here}} + +public: + S2() : a(0) {} + S2(S2 &s2) : a(s2.a) {} + static float S2s; // expected-note 2 {{static data member is predetermined as shared}} + static const float S2sc; +}; +const float S2::S2sc = 0; // expected-note 2 {{'S2sc' defined here}} +S2 b; // expected-note 3 {{'b' defined here}} +const S2 ba[5]; // expected-note 2 {{'ba' defined here}} +class S3 { + int a; + +public: + int b; + S3() : a(0) {} + S3(const S3 &s3) : a(s3.a) {} + S3 operator+(const S3 &arg1) { return arg1; } +}; +int operator+(const S3 &arg1, const S3 &arg2) { return 5; } +S3 c; // expected-note 3 {{'c' defined here}} +const S3 ca[5]; // expected-note 2 {{'ca' defined here}} +extern const int f; // expected-note 4 {{'f' declared here}} +class S4 { + int a; + S4(); // expected-note {{implicitly declared private here}} + S4(const S4 &s4); + S4 &operator+(const S4 &arg) { return (*this); } + +public: + S4(int v) : a(v) {} +}; +S4 &operator&=(S4 &arg1, S4 &arg2) { return arg1; } +class S5 { + int a; + S5() : a(0) {} // expected-note {{implicitly declared private here}} + S5(const S5 &s5) : a(s5.a) {} + S5 &operator+(const S5 &arg); + +public: + S5(int v) : a(v) {} +}; +class S6 { // expected-note 3 {{candidate function (the implicit copy assignment operator) not viable: no known conversion from 'int' to 'const S6' for 1st argument}} +#if __cplusplus >= 201103L // C++11 or later +// expected-note@-2 3 {{candidate function (the implicit move assignment operator) not viable}} +#endif + int a; + +public: + S6() : a(6) {} + operator int() { return 6; } +} o; + +S3 h, k; +#pragma omp threadprivate(h) // expected-note 2 {{defined as threadprivate or thread local}} + +template <class T> // expected-note {{declared here}} +T tmain(T argc) { + const T d = T(); // expected-note 4 {{'d' defined here}} + const T da[5] = {T()}; // expected-note 2 {{'da' defined here}} + T qa[5] = {T()}; + T i; + T &j = i; // expected-note 4 {{'j' defined here}} + S3 &p = k; // expected-note 2 {{'p' defined here}} + const T &r = da[(int)i]; // expected-note 2 {{'r' defined here}} + T &q = qa[(int)i]; // expected-note 2 {{'q' defined here}} + T fl; +#pragma omp target teams distribute simd reduction // expected-error {{expected '(' after 'reduction'}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction + // expected-error {{expected '(' after 'reduction'}} expected-warning {{extra tokens at the end of '#pragma omp target teams distribute simd' are ignored}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction( // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction(- // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction() // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction(*) // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected expression}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction(\) // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction(& : argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{invalid operands to binary expression ('float' and 'float')}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction(| : argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{invalid operands to binary expression ('float' and 'float')}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction(|| : argc ? i : argc) // expected-error 2 {{expected variable name, array element or array section}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction(foo : argc) //expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'float'}} expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'int'}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction(&& : argc) + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction(^ : T) // expected-error {{'T' does not refer to a value}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction(max : h.b) // expected-error {{expected variable name, array element or array section}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}} expected-error {{const-qualified list item cannot be reduction}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction(+ : o) // expected-error 2 {{no viable overloaded '='}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd private(i), reduction(+ : j), reduction(+ : q) // expected-error 4 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}} + for (int j=0; j<100; j++) foo(); +#pragma omp parallel private(k) +#pragma omp target teams distribute simd reduction(+ : p), reduction(+ : p) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction(+ : p), reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 2 {{previously referenced here}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}} + for (int j=0; j<100; j++) foo(); +#pragma omp parallel shared(i) +#pragma omp parallel reduction(min : i) +#pragma omp target teams distribute simd reduction(max : j) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction(+ : fl) + for (int j=0; j<100; j++) foo(); + + return T(); +} + +namespace A { +double x; +#pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}} +} +namespace B { +using A::x; +} + +int main(int argc, char **argv) { + const int d = 5; // expected-note 2 {{'d' defined here}} + const int da[5] = {0}; // expected-note {{'da' defined here}} + int qa[5] = {0}; + S4 e(4); + S5 g(5); + int i; + int &j = i; // expected-note 2 {{'j' defined here}} + S3 &p = k; // expected-note 2 {{'p' defined here}} + const int &r = da[i]; // expected-note {{'r' defined here}} + int &q = qa[i]; // expected-note {{'q' defined here}} + float fl; +#pragma omp target teams distribute simd reduction // expected-error {{expected '(' after 'reduction'}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction + // expected-error {{expected '(' after 'reduction'}} expected-warning {{extra tokens at the end of '#pragma omp target teams distribute simd' are ignored}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction( // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction(- // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction() // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction(*) // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected expression}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction(\) // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction(foo : argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max'}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction(| : argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction(|| : argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name, array element or array section}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction(~ : argc) // expected-error {{expected unqualified-id}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction(&& : argc) + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction(^ : S1) // expected-error {{'S1' does not refer to a value}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified list item cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified list item cannot be reduction}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction(max : h.b) // expected-error {{expected variable name, array element or array section}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction(& : e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{invalid operands to binary expression ('S4' and 'S4')}} expected-error {{calling a private constructor of class 'S5'}} expected-error {{invalid operands to binary expression ('S5' and 'S5')}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction(+ : h, k, B::x) // expected-error 2 {{threadprivate or thread local variable cannot be reduction}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction(+ : o) // expected-error {{no viable overloaded '='}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd private(i), reduction(+ : j), reduction(+ : q) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}} + for (int j=0; j<100; j++) foo(); +#pragma omp parallel private(k) +#pragma omp target teams distribute simd reduction(+ : p), reduction(+ : p) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction(+ : p), reduction(+ : p) // expected-error {{variable can appear only once in OpenMP 'reduction' clause}} expected-note {{previously referenced here}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction(+ : r) // expected-error {{const-qualified list item cannot be reduction}} + for (int j=0; j<100; j++) foo(); +#pragma omp parallel shared(i) +#pragma omp parallel reduction(min : i) +#pragma omp target teams distribute simd reduction(max : j) // expected-error {{argument of OpenMP clause 'reduction' must reference the same object in all threads}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd reduction(+ : fl) + for (int j=0; j<100; j++) foo(); + static int m; +#pragma omp target teams distribute simd reduction(+ : m) // OK + for (int j=0; j<100; j++) foo(); + + return tmain(argc) + tmain(fl); // expected-note {{in instantiation of function template specialization 'tmain<int>' requested here}} expected-note {{in instantiation of function template specialization 'tmain<float>' requested here}} +} diff --git a/test/OpenMP/target_teams_distribute_simd_safelen_messages.cpp b/test/OpenMP/target_teams_distribute_simd_safelen_messages.cpp new file mode 100644 index 000000000000..1f41c537ced6 --- /dev/null +++ b/test/OpenMP/target_teams_distribute_simd_safelen_messages.cpp @@ -0,0 +1,133 @@ +// RUN: %clang_cc1 -verify -fopenmp %s +// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s +// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s + +void foo() { +} + +#if __cplusplus >= 201103L +// expected-note@+2 4 {{declared here}} +#endif +bool foobool(int argc) { + return argc; +} + +struct S1; // expected-note {{declared here}} + +template <class T, typename S, int N, int ST> // expected-note {{declared here}} +T tmain(T argc, S **argv) { //expected-note 2 {{declared here}} + +#pragma omp target teams distribute simd safelen // expected-error {{expected '(' after 'safelen'}} + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i-ST]; + +#pragma omp target teams distribute simd safelen ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i-ST]; + +#pragma omp target teams distribute simd safelen () // expected-error {{expected expression}} + for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST]; + +#pragma omp target teams distribute simd safelen (argc // expected-note {{to match this '('}} expected-error 2 {{expression is not an integral constant expression}} expected-note 2 {{read of non-const variable 'argc' is not allowed in a constant expression}} expected-error {{expected ')'}} + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i-ST]; + +#pragma omp target teams distribute simd safelen (ST // expected-error {{argument to 'safelen' clause must be a strictly positive integer value}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i-ST]; + +#pragma omp target teams distribute simd safelen (1)) // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute simd' are ignored}} + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i-ST]; + +#pragma omp target teams distribute simd safelen ((ST > 0) ? 1 + ST : 2) + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i-ST]; + +#if __cplusplus >= 201103L + // expected-note@+2 2 {{non-constexpr function 'foobool' cannot be used in a constant expression}} +#endif +#pragma omp target teams distribute simd safelen (foobool(argc)), safelen (true), safelen (-5) // expected-error 2 {{directive '#pragma omp target teams distribute simd' cannot contain more than one 'safelen' clause}} expected-error 2 {{argument to 'safelen' clause must be a strictly positive integer value}} expected-error 2 {{expression is not an integral constant expression}} + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i-ST]; + +#pragma omp target teams distribute simd safelen (S) // expected-error {{'S' does not refer to a value}} + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i-ST]; + +#if __cplusplus <= 199711L + // expected-error@+4 2 {{expression is not an integral constant expression}} +#else + // expected-error@+2 2 {{integral constant expression must have integral or unscoped enumeration type, not 'char *'}} +#endif +#pragma omp target teams distribute simd safelen (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i-ST]; + +#pragma omp target teams distribute simd safelen (4) + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i-ST]; + +#pragma omp target teams distribute simd safelen (N) // expected-error {{argument to 'safelen' clause must be a strictly positive integer value}} + for (T i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i-ST]; + + return argc; +} + +int main(int argc, char **argv) { +#pragma omp target teams distribute simd safelen // expected-error {{expected '(' after 'safelen'}} + for (int i = 4; i < 12; i++) + argv[0][i] = argv[0][i] - argv[0][i-4]; + +#pragma omp target teams distribute simd safelen ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int i = 4; i < 12; i++) + argv[0][i] = argv[0][i] - argv[0][i-4]; + +#pragma omp target teams distribute simd safelen () // expected-error {{expected expression}} + for (int i = 4; i < 12; i++) + argv[0][i] = argv[0][i] - argv[0][i-4]; + +#pragma omp target teams distribute simd safelen (4 // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int i = 4; i < 12; i++) + argv[0][i] = argv[0][i] - argv[0][i-4]; + +#pragma omp target teams distribute simd safelen (2+2)) // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute simd' are ignored}} + for (int i = 4; i < 12; i++) + argv[0][i] = argv[0][i] - argv[0][i-4]; + +#if __cplusplus >= 201103L + // expected-note@+2 {{non-constexpr function 'foobool' cannot be used in a constant expression}} +#endif +#pragma omp target teams distribute simd safelen (foobool(1) > 0 ? 1 : 2) // expected-error {{expression is not an integral constant expression}} + for (int i = 4; i < 12; i++) + argv[0][i] = argv[0][i] - argv[0][i-4]; + +#if __cplusplus >= 201103L + // expected-note@+2 {{non-constexpr function 'foobool' cannot be used in a constant expression}} +#endif +#pragma omp target teams distribute simd safelen (foobool(argc)), safelen (true), safelen (-5) // expected-error 2 {{argument to 'safelen' clause must be a strictly positive integer value}} expected-error 2 {{directive '#pragma omp target teams distribute simd' cannot contain more than one 'safelen' clause}} expected-error {{expression is not an integral constant expression}} + for (int i = 4; i < 12; i++) + argv[0][i] = argv[0][i] - argv[0][i-4]; + +#pragma omp target teams distribute simd safelen (S1) // expected-error {{'S1' does not refer to a value}} + for (int i = 4; i < 12; i++) + argv[0][i] = argv[0][i] - argv[0][i-4]; + +#if __cplusplus <= 199711L + // expected-error@+4 {{expression is not an integral constant expression}} +#else + // expected-error@+2 {{integral constant expression must have integral or unscoped enumeration type, not 'char *'}} +#endif +#pragma omp target teams distribute simd safelen (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int i = 4; i < 12; i++) + argv[0][i] = argv[0][i] - argv[0][i-4]; + +// expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, -1, -2>' requested here}} +#pragma omp target teams distribute simd safelen(safelen(tmain<int, char, -1, -2>(argc, argv) // expected-error 2 {{expected ')'}} expected-note 2 {{to match this '('}} + foo(); // expected-error {{statement after '#pragma omp target teams distribute simd' must be a for loop}} + +// expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, 12, 4>' requested here}} + return tmain<int, char, 12, 4>(argc, argv); +} + diff --git a/test/OpenMP/target_teams_distribute_simd_shared_messages.cpp b/test/OpenMP/target_teams_distribute_simd_shared_messages.cpp new file mode 100644 index 000000000000..9f98ab9c80b6 --- /dev/null +++ b/test/OpenMP/target_teams_distribute_simd_shared_messages.cpp @@ -0,0 +1,106 @@ +// RUN: %clang_cc1 -verify -fopenmp %s + +void foo() { +} + +bool foobool(int argc) { + return argc; +} + +struct S1; // expected-note {{declared here}} +extern S1 a; +class S2 { + mutable int a; +public: + S2():a(0) { } + S2(S2 &s2):a(s2.a) { } +}; +const S2 b; +const S2 ba[5]; +class S3 { + int a; +public: + S3():a(0) { } + S3(S3 &s3):a(s3.a) { } +}; +const S3 c; +const S3 ca[5]; +extern const int f; +class S4 { + int a; + S4(); + S4(const S4 &s4); +public: + S4(int v):a(v) { } +}; +class S5 { + int a; + S5():a(0) {} + S5(const S5 &s5):a(s5.a) { } +public: + S5(int v):a(v) { } +}; + +S3 h; +#pragma omp threadprivate(h) // expected-note {{defined as threadprivate or thread local}} + +namespace A { +double x; +#pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}} +} +namespace B { +using A::x; +} + +int main(int argc, char **argv) { + const int d = 5; + const int da[5] = { 0 }; + S4 e(4); + S5 g(5); + int i; + int &j = i; + #pragma omp target teams distribute simd shared // expected-error {{expected '(' after 'shared'}} + for (int j=0; j<100; j++) foo(); + #pragma omp target teams distribute simd shared ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int j=0; j<100; j++) foo(); + #pragma omp target teams distribute simd shared () // expected-error {{expected expression}} + for (int j=0; j<100; j++) foo(); + #pragma omp target teams distribute simd shared (argc // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int j=0; j<100; j++) foo(); + #pragma omp target teams distribute simd shared (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int j=0; j<100; j++) foo(); + #pragma omp target teams distribute simd shared (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}} + for (int j=0; j<100; j++) foo(); + #pragma omp target teams distribute simd shared (argc) + for (int j=0; j<100; j++) foo(); + #pragma omp target teams distribute simd shared (S1) // expected-error {{'S1' does not refer to a value}} + for (int j=0; j<100; j++) foo(); + #pragma omp target teams distribute simd shared (a, b, c, d, f) + for (int j=0; j<100; j++) foo(); + #pragma omp target teams distribute simd shared (argv[1]) // expected-error {{expected variable name}} + for (int j=0; j<100; j++) foo(); + #pragma omp target teams distribute simd shared(ba) + for (int j=0; j<100; j++) foo(); + #pragma omp target teams distribute simd shared(ca) + for (int j=0; j<100; j++) foo(); + #pragma omp target teams distribute simd shared(da) + for (int j=0; j<100; j++) foo(); + #pragma omp target teams distribute simd shared(e, g) + for (int j=0; j<100; j++) foo(); + #pragma omp target teams distribute simd shared(h, B::x) // expected-error 2 {{threadprivate or thread local variable cannot be shared}} + for (int j=0; j<100; j++) foo(); + #pragma omp target teams distribute simd private(i), shared(i) // expected-error {{private variable cannot be shared}} expected-note {{defined as private}} + for (int j=0; j<100; j++) foo(); + #pragma omp target teams distribute simd firstprivate(i), shared(i) // expected-error {{firstprivate variable cannot be shared}} expected-note {{defined as firstprivate}} + for (int j=0; j<100; j++) foo(); + #pragma omp target teams distribute simd private(i) + for (int j=0; j<100; j++) foo(); + #pragma omp target teams distribute simd shared(i) + for (int j=0; j<100; j++) foo(); + #pragma omp target teams distribute simd shared(j) + for (int j=0; j<100; j++) foo(); + #pragma omp target teams distribute simd firstprivate(i) + for (int j=0; j<100; j++) foo(); + + return 0; +} diff --git a/test/OpenMP/target_teams_distribute_simd_simdlen_messages.cpp b/test/OpenMP/target_teams_distribute_simd_simdlen_messages.cpp new file mode 100644 index 000000000000..1b7ad66af69e --- /dev/null +++ b/test/OpenMP/target_teams_distribute_simd_simdlen_messages.cpp @@ -0,0 +1,133 @@ +// RUN: %clang_cc1 -verify -fopenmp %s +// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s +// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s + +void foo() { +} + +#if __cplusplus >= 201103L +// expected-note@+2 4 {{declared here}} +#endif +bool foobool(int argc) { + return argc; +} + +struct S1; // expected-note {{declared here}} + +template <class T, typename S, int N, int ST> // expected-note {{declared here}} +T tmain(T argc, S **argv) { //expected-note 2 {{declared here}} + +#pragma omp target teams distribute simd safelen // expected-error {{expected '(' after 'safelen'}} + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i-ST]; + +#pragma omp target teams distribute simd safelen ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i-ST]; + +#pragma omp target teams distribute simd safelen () // expected-error {{expected expression}} + for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST]; + +#pragma omp target teams distribute simd safelen (argc // expected-note {{to match this '('}} expected-error 2 {{expression is not an integral constant expression}} expected-note 2 {{read of non-const variable 'argc' is not allowed in a constant expression}} expected-error {{expected ')'}} + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i-ST]; + +#pragma omp target teams distribute simd safelen (ST // expected-error {{argument to 'safelen' clause must be a strictly positive integer value}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i-ST]; + +#pragma omp target teams distribute simd safelen (1)) // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute simd' are ignored}} + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i-ST]; + +#pragma omp target teams distribute simd safelen ((ST > 0) ? 1 + ST : 2) + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i-ST]; + +#if __cplusplus >= 201103L + // expected-note@+2 2 {{non-constexpr function 'foobool' cannot be used in a constant expression}} +#endif +#pragma omp target teams distribute simd safelen (foobool(argc)), safelen (true), safelen (-5) // expected-error 2 {{directive '#pragma omp target teams distribute simd' cannot contain more than one 'safelen' clause}} expected-error 2 {{argument to 'safelen' clause must be a strictly positive integer value}} expected-error 2 {{expression is not an integral constant expression}} + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i-ST]; + +#pragma omp target teams distribute simd safelen (S) // expected-error {{'S' does not refer to a value}} + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i-ST]; + +#if __cplusplus <= 199711L + // expected-error@+4 2 {{expression is not an integral constant expression}} +#else + // expected-error@+2 2 {{integral constant expression must have integral or unscoped enumeration type, not 'char *'}} +#endif +#pragma omp target teams distribute simd safelen (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i-ST]; + +#pragma omp target teams distribute simd safelen (4) + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i-ST]; + +#pragma omp target teams distribute simd safelen (N) // expected-error {{argument to 'safelen' clause must be a strictly positive integer value}} + for (T i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i-ST]; + + return argc; +} + +int main(int argc, char **argv) { +#pragma omp target teams distribute simd safelen // expected-error {{expected '(' after 'safelen'}} + for (int i = 4; i < 12; i++) + argv[0][i] = argv[0][i] - argv[0][i-4]; + +#pragma omp target teams distribute simd safelen ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int i = 4; i < 12; i++) + argv[0][i] = argv[0][i] - argv[0][i-4]; + +#pragma omp target teams distribute simd safelen () // expected-error {{expected expression}} + for (int i = 4; i < 12; i++) + argv[0][i] = argv[0][i] - argv[0][i-4]; + +#pragma omp target teams distribute simd safelen (4 // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int i = 4; i < 12; i++) + argv[0][i] = argv[0][i] - argv[0][i-4]; + +#pragma omp target teams distribute simd safelen (2+2)) // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute simd' are ignored}} + for (int i = 4; i < 12; i++) + argv[0][i] = argv[0][i] - argv[0][i-4]; + +#if __cplusplus >= 201103L + // expected-note@+2 {{non-constexpr function 'foobool' cannot be used in a constant expression}} +#endif +#pragma omp target teams distribute simd safelen (foobool(1) > 0 ? 1 : 2) // expected-error {{expression is not an integral constant expression}} + for (int i = 4; i < 12; i++) + argv[0][i] = argv[0][i] - argv[0][i-4]; + +#if __cplusplus >= 201103L + // expected-note@+2 {{non-constexpr function 'foobool' cannot be used in a constant expression}} +#endif +#pragma omp target teams distribute simd safelen (foobool(argc)), safelen (true), safelen (-5) // expected-error 2 {{argument to 'safelen' clause must be a strictly positive integer value}} expected-error 2 {{directive '#pragma omp target teams distribute simd' cannot contain more than one 'safelen' clause}} expected-error {{expression is not an integral constant expression}} + for (int i = 4; i < 12; i++) + argv[0][i] = argv[0][i] - argv[0][i-4]; + +#pragma omp target teams distribute simd safelen (S1) // expected-error {{'S1' does not refer to a value}} + for (int i = 4; i < 12; i++) + argv[0][i] = argv[0][i] - argv[0][i-4]; + +#if __cplusplus <= 199711L + // expected-error@+4 {{expression is not an integral constant expression}} +#else + // expected-error@+2 {{integral constant expression must have integral or unscoped enumeration type, not 'char *'}} +#endif +#pragma omp target teams distribute simd safelen (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int i = 4; i < 12; i++) + argv[0][i] = argv[0][i] - argv[0][i-4]; + + // expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, -1, -2>' requested here}} +#pragma omp target teams distribute simd safelen(safelen(tmain<int, char, -1, -2>(argc, argv) // expected-error 2 {{expected ')'}} expected-note 2 {{to match this '('}} + foo(); // expected-error {{statement after '#pragma omp target teams distribute simd' must be a for loop}} + + // expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, 12, 4>' requested here}} + return tmain<int, char, 12, 4>(argc, argv); +} + diff --git a/test/OpenMP/target_teams_distribute_simd_thread_limit_messages.cpp b/test/OpenMP/target_teams_distribute_simd_thread_limit_messages.cpp new file mode 100644 index 000000000000..357f5dde313b --- /dev/null +++ b/test/OpenMP/target_teams_distribute_simd_thread_limit_messages.cpp @@ -0,0 +1,85 @@ +// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s + +void foo() { +} + +bool foobool(int argc) { + return argc; +} + +struct S1; // expected-note 2 {{declared here}} + +template <typename T, int C> // expected-note {{declared here}} +T tmain(T argc) { + char **a; +#pragma omp target teams distribute simd thread_limit(C) + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd thread_limit(T) // expected-error {{'T' does not refer to a value}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd thread_limit // expected-error {{expected '(' after 'thread_limit'}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd thread_limit( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd thread_limit() // expected-error {{expected expression}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd thread_limit(argc // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd thread_limit(argc)) // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute simd' are ignored}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd thread_limit(argc > 0 ? a[1] : a[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd thread_limit(argc + argc) + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd thread_limit(argc), thread_limit (argc+1) // expected-error {{directive '#pragma omp target teams distribute simd' cannot contain more than one 'thread_limit' clause}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd thread_limit(S1) // expected-error {{'S1' does not refer to a value}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd thread_limit(-2) // expected-error {{argument to 'thread_limit' clause must be a strictly positive integer value}} + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd thread_limit(-10u) + for (int j=0; j<100; j++) foo(); +#pragma omp target teams distribute simd thread_limit(3.14) // expected-error 2 {{expression must have integral or unscoped enumeration type, not 'double'}} + for (int j=0; j<100; j++) foo(); + + return 0; +} + +int main(int argc, char **argv) { +#pragma omp target teams distribute simd thread_limit // expected-error {{expected '(' after 'thread_limit'}} + for (int j=0; j<100; j++) foo(); + +#pragma omp target teams distribute simd thread_limit ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int j=0; j<100; j++) foo(); + +#pragma omp target teams distribute simd thread_limit () // expected-error {{expected expression}} + for (int j=0; j<100; j++) foo(); + +#pragma omp target teams distribute simd thread_limit (argc // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int j=0; j<100; j++) foo(); + +#pragma omp target teams distribute simd thread_limit (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute simd' are ignored}} + for (int j=0; j<100; j++) foo(); + +#pragma omp target teams distribute simd thread_limit (argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} + for (int j=0; j<100; j++) foo(); + +#pragma omp target teams distribute simd thread_limit (argc + argc) + for (int j=0; j<100; j++) foo(); + +#pragma omp target teams distribute simd thread_limit (argc), thread_limit (argc+1) // expected-error {{directive '#pragma omp target teams distribute simd' cannot contain more than one 'thread_limit' clause}} + for (int j=0; j<100; j++) foo(); + +#pragma omp target teams distribute simd thread_limit (S1) // expected-error {{'S1' does not refer to a value}} + for (int j=0; j<100; j++) foo(); + +#pragma omp target teams distribute simd thread_limit (-2) // expected-error {{argument to 'thread_limit' clause must be a strictly positive integer value}} + for (int j=0; j<100; j++) foo(); + +#pragma omp target teams distribute simd thread_limit (-10u) + for (int j=0; j<100; j++) foo(); + +#pragma omp target teams distribute simd thread_limit (3.14) // expected-error {{expression must have integral or unscoped enumeration type, not 'double'}} + for (int j=0; j<100; j++) foo(); + + return tmain<int, 10>(argc); // expected-note {{in instantiation of function template specialization 'tmain<int, 10>' requested here}} +} diff --git a/test/OpenMP/threadprivate_codegen.cpp b/test/OpenMP/threadprivate_codegen.cpp index 09f5ed5060ba..318415761ac7 100644 --- a/test/OpenMP/threadprivate_codegen.cpp +++ b/test/OpenMP/threadprivate_codegen.cpp @@ -179,9 +179,9 @@ struct S5 { // CHECK-TLS-DAG: @__dso_handle = external global i8 // CHECK-TLS-DAG: [[GS1_TLS_INIT:@_ZTHL3gs1]] = internal alias void (), void ()* @__tls_init // CHECK-TLS-DAG: [[ARR_X_TLS_INIT:@_ZTH5arr_x]] = alias void (), void ()* @__tls_init -// CHECK-TLS-DAG: [[ST_INT_ST_TLS_INIT:@_ZTHN2STIiE2stE]] = linkonce_odr alias void (), void ()* @__tls_init -// CHECK-TLS-DAG: [[ST_FLOAT_ST_TLS_INIT:@_ZTHN2STIfE2stE]] = linkonce_odr alias void (), void ()* @__tls_init -// CHECK-TLS-DAG: [[ST_S4_ST_TLS_INIT:@_ZTHN2STI2S4E2stE]] = linkonce_odr alias void (), void ()* @__tls_init + + +// CHECK-TLS-DAG: [[ST_S4_ST_TLS_INIT:@_ZTHN2STI2S4E2stE]] = linkonce_odr alias void (), void ()* [[ST_S4_ST_CXX_INIT:@[^, ]*]] struct Static { static S3 s; @@ -640,11 +640,11 @@ int main() { // CHECK-TLS: ret [2 x [3 x [[S1]]]]* [[ARR_X]] // CHECK-TLS: } // CHECK-TLS: define {{.*}} i32* [[ST_INT_ST_TLS_INITD]] {{#[0-9]+}} { -// CHECK-TLS: call void [[ST_INT_ST_TLS_INIT]] +// CHECK-TLS-NOT: call // CHECK-TLS: ret i32* [[ST_INT_ST]] // CHECK-TLS: } // CHECK-TLS: define {{.*}} float* [[ST_FLOAT_ST_TLS_INITD]] {{#[0-9]+}} { -// CHECK-TLS: call void [[ST_FLOAT_ST_TLS_INIT]] +// CHECK-TLS-NOT: call // CHECK-TLS: ret float* [[ST_FLOAT_ST]] // CHECK-TLS: } // CHECK-TLS: define {{.*}} [[S4]]* [[ST_S4_ST_TLS_INITD]] {{#[0-9]+}} { @@ -923,7 +923,7 @@ int foobar() { // CHECK-TLS: define {{.*}}void [[SM_CTOR2]]([[SMAIN]]* {{.*}}, i32 {{.*}}) // CHECK-TLS: define {{.*}}void [[SM_DTOR2]]([[SMAIN]]* {{.*}}) -// CHECK-TLS: define internal void [[ST_S4_ST_CXX_INIT:@.*]]() +// CHECK-TLS: define internal void [[ST_S4_ST_CXX_INIT]]() // CHECK-TLS: call void [[ST_S4_ST_CTOR1:@.*]]([[S4]]* [[ST_S4_ST]], i32 23) // CHECK-TLS: call i32 @__cxa_thread_atexit(void (i8*)* bitcast (void ([[S4]]*)* [[ST_S4_ST_DTOR1:.*]] to void (i8*)*), i8* bitcast ([[S4]]* [[ST_S4_ST]] to i8*) // CHECK-TLS: } @@ -945,7 +945,7 @@ int foobar() { // CHECK-TLS: call void [[GS1_CXX_INIT]] // CHECK-TLS-NOT: call void [[GS2_CXX_INIT]] // CHECK-TLS: call void [[ARR_X_CXX_INIT]] -// CHECK-TLS: call void [[ST_S4_ST_CXX_INIT]] +// CHECK-TLS-NOT: call void [[ST_S4_ST_CXX_INIT]] // CHECK-TLS: [[DONE_LABEL]] // CHECK-TLS-DAG: declare {{.*}} void [[GS3_TLS_INIT]] diff --git a/test/PCH/uses-seh.cpp b/test/PCH/uses-seh.cpp new file mode 100644 index 000000000000..6fbfc9766c48 --- /dev/null +++ b/test/PCH/uses-seh.cpp @@ -0,0 +1,29 @@ +// Make SEH works in PCH +// +// Test this without pch. +// RUN: %clang_cc1 -fms-extensions -triple x86_64-windows-msvc -std=c++11 -include %s -emit-llvm -o - %s | FileCheck %s + +// Test with pch. +// RUN: %clang_cc1 -fms-extensions -triple x86_64-windows-msvc -std=c++11 -emit-pch -o %t %s +// RUN: %clang_cc1 -fms-extensions -triple x86_64-windows-msvc -std=c++11 -include-pch %t -emit-llvm -o - %s | FileCheck %s + +#ifndef HEADER +#define HEADER + +int shouldCatch(); +inline int f() { + __try { + } __except (shouldCatch()) { + } + return 0; +} +int x = f(); + +// CHECK: define linkonce_odr i32 @"\01?f@@YAHXZ"() +// CHECK: define internal i32 @"\01?filt$0@0@f@@"({{.*}}) + +#else + +// empty + +#endif diff --git a/test/Preprocessor/predefined-arch-macros.c b/test/Preprocessor/predefined-arch-macros.c index 51b587e403e0..883cc4d19b29 100644 --- a/test/Preprocessor/predefined-arch-macros.c +++ b/test/Preprocessor/predefined-arch-macros.c @@ -1849,6 +1849,88 @@ // CHECK_BDVER4_M64: #define __tune_bdver4__ 1 // CHECK_BDVER4_M64: #define __x86_64 1 // CHECK_BDVER4_M64: #define __x86_64__ 1 +// RUN: %clang -march=znver1 -m32 -E -dM %s -o - 2>&1 \ +// RUN: -target i386-unknown-linux \ +// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_ZNVER1_M32 +// CHECK_ZNVER1_M32-NOT: #define __3dNOW_A__ 1 +// CHECK_ZNVER1_M32-NOT: #define __3dNOW__ 1 +// CHECK_ZNVER1_M32: #define __ADX__ 1 +// CHECK_ZNVER1_M32: #define __AES__ 1 +// CHECK_ZNVER1_M32: #define __AVX2__ 1 +// CHECK_ZNVER1_M32: #define __AVX__ 1 +// CHECK_ZNVER1_M32: #define __BMI2__ 1 +// CHECK_ZNVER1_M32: #define __BMI__ 1 +// CHECK_ZNVER1_M32: #define __F16C__ 1 +// CHECK_ZNVER1_M32: #define __FMA__ 1 +// CHECK_ZNVER1_M32: #define __FSGSBASE__ 1 +// CHECK_ZNVER1_M32: #define __LZCNT__ 1 +// CHECK_ZNVER1_M32: #define __MMX__ 1 +// CHECK_ZNVER1_M32: #define __PCLMUL__ 1 +// CHECK_ZNVER1_M32: #define __POPCNT__ 1 +// CHECK_ZNVER1_M32: #define __PRFCHW__ 1 +// CHECK_ZNVER1_M32: #define __RDRND__ 1 +// CHECK_ZNVER1_M32: #define __RDSEED__ 1 +// CHECK_ZNVER1_M32: #define __SHA__ 1 +// CHECK_ZNVER1_M32: #define __SSE2_MATH__ 1 +// CHECK_ZNVER1_M32: #define __SSE2__ 1 +// CHECK_ZNVER1_M32: #define __SSE3__ 1 +// CHECK_ZNVER1_M32: #define __SSE4A__ 1 +// CHECK_ZNVER1_M32: #define __SSE4_1__ 1 +// CHECK_ZNVER1_M32: #define __SSE4_2__ 1 +// CHECK_ZNVER1_M32: #define __SSE_MATH__ 1 +// CHECK_ZNVER1_M32: #define __SSE__ 1 +// CHECK_ZNVER1_M32: #define __SSSE3__ 1 +// CHECK_ZNVER1_M32: #define __XSAVEC__ 1 +// CHECK_ZNVER1_M32: #define __XSAVEOPT__ 1 +// CHECK_ZNVER1_M32: #define __XSAVES__ 1 +// CHECK_ZNVER1_M32: #define __XSAVE__ 1 +// CHECK_ZNVER1_M32: #define __i386 1 +// CHECK_ZNVER1_M32: #define __i386__ 1 +// CHECK_ZNVER1_M32: #define __tune_znver1__ 1 +// CHECK_ZNVER1_M32: #define __znver1 1 +// CHECK_ZNVER1_M32: #define __znver1__ 1 +// RUN: %clang -march=znver1 -m64 -E -dM %s -o - 2>&1 \ +// RUN: -target i386-unknown-linux \ +// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_ZNVER1_M64 +// CHECK_ZNVER1_M64-NOT: #define __3dNOW_A__ 1 +// CHECK_ZNVER1_M64-NOT: #define __3dNOW__ 1 +// CHECK_ZNVER1_M64: #define __ADX__ 1 +// CHECK_ZNVER1_M64: #define __AES__ 1 +// CHECK_ZNVER1_M64: #define __AVX2__ 1 +// CHECK_ZNVER1_M64: #define __AVX__ 1 +// CHECK_ZNVER1_M64: #define __BMI2__ 1 +// CHECK_ZNVER1_M64: #define __BMI__ 1 +// CHECK_ZNVER1_M64: #define __F16C__ 1 +// CHECK_ZNVER1_M64: #define __FMA__ 1 +// CHECK_ZNVER1_M64: #define __FSGSBASE__ 1 +// CHECK_ZNVER1_M64: #define __LZCNT__ 1 +// CHECK_ZNVER1_M64: #define __MMX__ 1 +// CHECK_ZNVER1_M64: #define __PCLMUL__ 1 +// CHECK_ZNVER1_M64: #define __POPCNT__ 1 +// CHECK_ZNVER1_M64: #define __PRFCHW__ 1 +// CHECK_ZNVER1_M64: #define __RDRND__ 1 +// CHECK_ZNVER1_M64: #define __RDSEED__ 1 +// CHECK_ZNVER1_M64: #define __SHA__ 1 +// CHECK_ZNVER1_M64: #define __SSE2_MATH__ 1 +// CHECK_ZNVER1_M64: #define __SSE2__ 1 +// CHECK_ZNVER1_M64: #define __SSE3__ 1 +// CHECK_ZNVER1_M64: #define __SSE4A__ 1 +// CHECK_ZNVER1_M64: #define __SSE4_1__ 1 +// CHECK_ZNVER1_M64: #define __SSE4_2__ 1 +// CHECK_ZNVER1_M64: #define __SSE_MATH__ 1 +// CHECK_ZNVER1_M64: #define __SSE__ 1 +// CHECK_ZNVER1_M64: #define __SSSE3__ 1 +// CHECK_ZNVER1_M64: #define __XSAVEC__ 1 +// CHECK_ZNVER1_M64: #define __XSAVEOPT__ 1 +// CHECK_ZNVER1_M64: #define __XSAVES__ 1 +// CHECK_ZNVER1_M64: #define __XSAVE__ 1 +// CHECK_ZNVER1_M64: #define __amd64 1 +// CHECK_ZNVER1_M64: #define __amd64__ 1 +// CHECK_ZNVER1_M64: #define __tune_znver1__ 1 +// CHECK_ZNVER1_M64: #define __x86_64 1 +// CHECK_ZNVER1_M64: #define __x86_64__ 1 +// CHECK_ZNVER1_M64: #define __znver1 1 +// CHECK_ZNVER1_M64: #define __znver1__ 1 // // End X86/GCC/Linux tests ------------------ diff --git a/test/Profile/gcc-flag-compatibility.c b/test/Profile/gcc-flag-compatibility.c index f685f69e4ba0..cfc1a3536608 100644 --- a/test/Profile/gcc-flag-compatibility.c +++ b/test/Profile/gcc-flag-compatibility.c @@ -18,14 +18,14 @@ // RUN: rm -rf %t.dir // RUN: mkdir -p %t.dir/some/path // RUN: llvm-profdata merge %S/Inputs/gcc-flag-compatibility.proftext -o %t.dir/some/path/default.profdata -// RUN: %clang %s -o - -mllvm -disable-llvm-passes -emit-llvm -S -fprofile-use=%t.dir/some/path | FileCheck -check-prefix=PROFILE-USE-2 %s +// RUN: %clang %s -o - -Xclang -disable-llvm-passes -emit-llvm -S -fprofile-use=%t.dir/some/path | FileCheck -check-prefix=PROFILE-USE-2 %s // PROFILE-USE-2: = !{!"branch_weights", i32 101, i32 2} // Check that -fprofile-use=some/path/file.prof reads some/path/file.prof // RUN: rm -rf %t.dir // RUN: mkdir -p %t.dir/some/path // RUN: llvm-profdata merge %S/Inputs/gcc-flag-compatibility.proftext -o %t.dir/some/path/file.prof -// RUN: %clang %s -o - -mllvm -disable-llvm-passes -emit-llvm -S -fprofile-use=%t.dir/some/path/file.prof | FileCheck -check-prefix=PROFILE-USE-3 %s +// RUN: %clang %s -o - -Xclang -disable-llvm-passes -emit-llvm -S -fprofile-use=%t.dir/some/path/file.prof | FileCheck -check-prefix=PROFILE-USE-3 %s // PROFILE-USE-3: = !{!"branch_weights", i32 101, i32 2} int X = 0; diff --git a/test/Sema/atomic-ops.c b/test/Sema/atomic-ops.c index 8ebf3eaed4af..d3ebdf67db0f 100644 --- a/test/Sema/atomic-ops.c +++ b/test/Sema/atomic-ops.c @@ -14,11 +14,7 @@ _Static_assert(__GCC_ATOMIC_WCHAR_T_LOCK_FREE == 2, ""); _Static_assert(__GCC_ATOMIC_SHORT_LOCK_FREE == 2, ""); _Static_assert(__GCC_ATOMIC_INT_LOCK_FREE == 2, ""); _Static_assert(__GCC_ATOMIC_LONG_LOCK_FREE == 2, ""); -#ifdef __i386__ -_Static_assert(__GCC_ATOMIC_LLONG_LOCK_FREE == 1, ""); -#else _Static_assert(__GCC_ATOMIC_LLONG_LOCK_FREE == 2, ""); -#endif _Static_assert(__GCC_ATOMIC_POINTER_LOCK_FREE == 2, ""); _Static_assert(__c11_atomic_is_lock_free(1), ""); diff --git a/test/Sema/warn-unreachable.c b/test/Sema/warn-unreachable.c index 31beff9cf1e0..34e0296a2049 100644 --- a/test/Sema/warn-unreachable.c +++ b/test/Sema/warn-unreachable.c @@ -1,4 +1,5 @@ // RUN: %clang_cc1 %s -fsyntax-only -verify -fblocks -Wunreachable-code-aggressive -Wno-unused-value -Wno-covered-switch-default -I %S/Inputs +// RUN: %clang_cc1 -fsyntax-only -fblocks -Wunreachable-code-aggressive -Wno-unused-value -Wno-covered-switch-default -fdiagnostics-parseable-fixits -I %S/Inputs %s 2>&1 | FileCheck %s #include "warn-unreachable.h" @@ -396,3 +397,57 @@ void test_with_paren_silencing(int x) { else calledFun(); } + +// rdar://24570531 + +struct StructWithPointer { + void *p; +}; + +void emitJustOneWarningForOr(struct StructWithPointer *s) { + if (1 || !s->p) // expected-note {{silence by adding parentheses to mark code as explicitly dead}} + return; // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:7-[[@LINE-1]]:7}:"/* DISABLES CODE */ (" + // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:8-[[@LINE-2]]:8}:")" + emitJustOneWarningForOr(s); // expected-warning {{code will never be executed}} +} + +void emitJustOneWarningForOrSilenced(struct StructWithPointer *s) { + if ((1) || !s->p) + return; + + emitJustOneWarningForOrSilenced(s); // no warning +} + +void emitJustOneWarningForOr2(struct StructWithPointer *s) { + if (1 || !s->p) // expected-warning {{code will never be executed}} + return; // expected-note@-1 {{silence by adding parentheses to mark code as explicitly dead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:7-[[@LINE-2]]:7}:"/* DISABLES CODE */ (" + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:8-[[@LINE-3]]:8}:")" +} + +void wrapOneInFixit(struct StructWithPointer *s) { + if (!s->p || 1) // expected-note {{silence by adding parentheses to mark code as explicitly dead}} + return; // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:16-[[@LINE-1]]:16}:"/* DISABLES CODE */ (" + // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:17-[[@LINE-2]]:17}:")" + wrapOneInFixit(s); // expected-warning {{code will never be executed}} +} + +void unaryOpNoFixit() { + if (- 1) + return; // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]] + unaryOpNoFixit(); // expected-warning {{code will never be executed}} +} + +void unaryOpStrictFixit(struct StructWithPointer *s) { + if (!(s->p && 0)) // expected-note {{silence by adding parentheses to mark code as explicitly dead}} + return; // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:17-[[@LINE-1]]:17}:"/* DISABLES CODE */ (" + // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:18-[[@LINE-2]]:18}:")" + unaryOpStrictFixit(s); // expected-warning {{code will never be executed}} +} + +void unaryOpFixitCastSubExpr(int x) { + if (! (int)0) // expected-note {{silence by adding parentheses to mark code as explicitly dead}} + return; // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:7-[[@LINE-1]]:7}:"/* DISABLES CODE */ (" + // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:15-[[@LINE-2]]:15}:")" + unaryOpFixitCastSubExpr(x); // expected-warning {{code will never be executed}} +} diff --git a/test/SemaCXX/coroutines.cpp b/test/SemaCXX/coroutines.cpp index a22383cd566b..158b1a7c7dd4 100644 --- a/test/SemaCXX/coroutines.cpp +++ b/test/SemaCXX/coroutines.cpp @@ -154,12 +154,11 @@ void mixed_await() { } void only_coreturn(void_tag) { - co_return; // expected-warning {{'co_return' used in a function that uses neither 'co_await' nor 'co_yield'}} + co_return; // OK } void mixed_coreturn(void_tag, bool b) { if (b) - // expected-warning@+1 {{'co_return' used in a function that uses neither}} co_return; // expected-note {{use of 'co_return'}} else return; // expected-error {{not allowed in coroutine}} diff --git a/test/SemaCXX/cxx0x-class.cpp b/test/SemaCXX/cxx0x-class.cpp index 2b1338f97fd7..8afb0fd6f3c0 100644 --- a/test/SemaCXX/cxx0x-class.cpp +++ b/test/SemaCXX/cxx0x-class.cpp @@ -37,3 +37,11 @@ namespace Foo { int y = x; }; } + +// Instantiating another default member initializer while parsing one should +// not cause us to mess up the 'this' override. +template<typename> struct DefaultMemberTemplate { int n = 0; }; +class DefaultMemberInitSelf { + DefaultMemberTemplate<int> t = {}; + int *p = &t.n; +}; diff --git a/test/SemaCXX/cxx1y-variable-templates_top_level.cpp b/test/SemaCXX/cxx1y-variable-templates_top_level.cpp index ec3e2b6f63d1..367f67bf5fa8 100644 --- a/test/SemaCXX/cxx1y-variable-templates_top_level.cpp +++ b/test/SemaCXX/cxx1y-variable-templates_top_level.cpp @@ -464,3 +464,8 @@ template <typename... Args> Variadic_t<Args...> Variadic; auto variadic1 = Variadic<>; auto variadic2 = Variadic<int, int>; #endif + +namespace VexingParse { + template <typename> int var; // expected-note {{declared here}} + int x(var); // expected-error {{cannot refer to variable template 'var' without a template argument list}} +} diff --git a/test/SemaCXX/diagnose_if-ext.cpp b/test/SemaCXX/diagnose_if-ext.cpp new file mode 100644 index 000000000000..d5625b501322 --- /dev/null +++ b/test/SemaCXX/diagnose_if-ext.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -Wpedantic -fsyntax-only %s -verify + +void foo() __attribute__((diagnose_if(1, "", "error"))); // expected-warning{{'diagnose_if' is a clang extension}} +void foo(int a) __attribute__((diagnose_if(a, "", "error"))); // expected-warning{{'diagnose_if' is a clang extension}} +// FIXME: When diagnose_if gets a CXX11 spelling, this should be enabled. +#if 0 +[[clang::diagnose_if(a, "", "error")]] void foo(double a); +#endif diff --git a/test/SemaCXX/uninitialized.cpp b/test/SemaCXX/uninitialized.cpp index 5769a0c028c8..7a23f3cef2c4 100644 --- a/test/SemaCXX/uninitialized.cpp +++ b/test/SemaCXX/uninitialized.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -Wall -Wuninitialized -Wno-unused-value -std=c++11 -verify %s +// RUN: %clang_cc1 -fsyntax-only -Wall -Wuninitialized -Wno-unused-value -std=c++1z -verify %s // definitions for std::move namespace std { @@ -1437,3 +1437,13 @@ void array_capture(bool b) { [fname]{}; } } + +void if_switch_init_stmt(int k) { + if (int n = 0; (n == k || k > 5)) {} + + if (int n; (n == k || k > 5)) {} // expected-warning {{uninitialized}} expected-note {{initialize}} + + switch (int n = 0; (n == k || k > 5)) {} // expected-warning {{boolean}} + + switch (int n; (n == k || k > 5)) {} // expected-warning {{uninitialized}} expected-note {{initialize}} expected-warning {{boolean}} +} diff --git a/test/SemaCXX/warn-shadow-in-lambdas.cpp b/test/SemaCXX/warn-shadow-in-lambdas.cpp index 575664482dbe..b0dcd122a540 100644 --- a/test/SemaCXX/warn-shadow-in-lambdas.cpp +++ b/test/SemaCXX/warn-shadow-in-lambdas.cpp @@ -137,3 +137,11 @@ void foo(int param) { // expected-note 1+ {{previous declaration is here}} auto g3 = [param] // expected-note {{variable 'param' is explicitly captured here}} (auto param) { ; }; // expected-warning {{declaration shadows a local variable}} } + +void avoidWarningWhenRedefining() { + int a = 1; + auto l = [b = a] { // expected-note {{previous definition is here}} + // Don't warn on redefinitions. + int b = 0; // expected-error {{redefinition of 'b'}} + }; +} diff --git a/test/SemaCXX/warn-shadow.cpp b/test/SemaCXX/warn-shadow.cpp index 9d68fe7c47a6..1316b6dd8871 100644 --- a/test/SemaCXX/warn-shadow.cpp +++ b/test/SemaCXX/warn-shadow.cpp @@ -97,3 +97,13 @@ void rdar8883302() { void test8() { int bob; // expected-warning {{declaration shadows a variable in the global namespace}} } + +namespace rdar29067894 { + +void avoidWarningWhenRedefining(int b) { // expected-note {{previous definition is here}} + int a = 0; // expected-note {{previous definition is here}} + int a = 1; // expected-error {{redefinition of 'a'}} + int b = 2; // expected-error {{redefinition of 'b'}} +} + +} diff --git a/test/SemaTemplate/deduction.cpp b/test/SemaTemplate/deduction.cpp index 0c0e7d599ccb..16e01a934630 100644 --- a/test/SemaTemplate/deduction.cpp +++ b/test/SemaTemplate/deduction.cpp @@ -383,6 +383,23 @@ namespace deduction_after_explicit_pack { template<typename... T> struct X { X(int); operator int(); }; template<typename... T> void p(T..., X<T...>, ...); // expected-note {{deduced conflicting}} void q() { p(X<int>(0), 0); } // expected-error {{no match}} + + struct A { + template <typename T> void f(T, void *, int = 0); // expected-note 2{{no known conversion from 'double' to 'void *' for 2nd argument}} + void f(); // expected-note 2{{requires 0}} + + template <typename T> static void g(T, void *, int = 0); // expected-note 2{{no known conversion from 'double' to 'void *' for 2nd argument}} + void g(); // expected-note 2{{requires 0}} + + void h() { + f(1.0, 2.0); // expected-error {{no match}} + g(1.0, 2.0); // expected-error {{no match}} + } + }; + void f(A a) { + a.f(1.0, 2.0); // expected-error {{no match}} + a.g(1.0, 2.0); // expected-error {{no match}} + } } namespace overload_vs_pack { diff --git a/test/SemaTemplate/temp_arg_template.cpp b/test/SemaTemplate/temp_arg_template.cpp index 67cde53c928b..b0df9149c6e0 100644 --- a/test/SemaTemplate/temp_arg_template.cpp +++ b/test/SemaTemplate/temp_arg_template.cpp @@ -100,3 +100,9 @@ struct S : public template_tuple<identity, identity> { void foo() { f7<identity>(); } + +namespace CheckDependentNonTypeParamTypes { + template<template<typename T, typename U, T v> class> struct A {}; // expected-note {{previous}} + template<typename T, typename U, U v> struct B {}; // expected-note {{different type}} + A<B> ab; // expected-error {{different template parameters}} +} diff --git a/test/SemaTemplate/temp_arg_template_cxx1z.cpp b/test/SemaTemplate/temp_arg_template_cxx1z.cpp index b6b283b53c6b..aa517c328599 100644 --- a/test/SemaTemplate/temp_arg_template_cxx1z.cpp +++ b/test/SemaTemplate/temp_arg_template_cxx1z.cpp @@ -70,30 +70,47 @@ namespace Auto { template<template<int*> typename T> struct TIntPtr {}; template<template<auto> typename T> struct TAuto {}; template<template<auto*> typename T> struct TAutoPtr {}; + template<template<decltype(auto)> typename T> struct TDecltypeAuto {}; template<auto> struct Auto; template<auto*> struct AutoPtr; + template<decltype(auto)> struct DecltypeAuto; template<int> struct Int; template<int*> struct IntPtr; TInt<Auto> ia; - TInt<AutoPtr> iap; // FIXME: ill-formed + TInt<AutoPtr> iap; // expected-error {{different template parameters}} + TInt<DecltypeAuto> ida; // FIXME expected-error {{different template parameters}} TInt<Int> ii; TInt<IntPtr> iip; // expected-error {{different template parameters}} TIntPtr<Auto> ipa; TIntPtr<AutoPtr> ipap; + TIntPtr<DecltypeAuto> ipda; // FIXME expected-error {{different template parameters}} TIntPtr<Int> ipi; // expected-error {{different template parameters}} TIntPtr<IntPtr> ipip; TAuto<Auto> aa; - TAuto<AutoPtr> aap; // FIXME: ill-formed - TAuto<Int> ai; // FIXME: ill-formed - TAuto<IntPtr> aip; // FIXME: ill-formed + TAuto<AutoPtr> aap; // expected-error {{different template parameters}} + TAuto<Int> ai; // expected-error {{different template parameters}} + TAuto<IntPtr> aip; // expected-error {{different template parameters}} TAutoPtr<Auto> apa; TAutoPtr<AutoPtr> apap; - TAutoPtr<Int> api; // FIXME: ill-formed - TAutoPtr<IntPtr> apip; // FIXME: ill-formed + TAutoPtr<Int> api; // expected-error {{different template parameters}} + TAutoPtr<IntPtr> apip; // expected-error {{different template parameters}} + + TDecltypeAuto<DecltypeAuto> dada; + TDecltypeAuto<Int> dai; // expected-error {{different template parameters}} + TDecltypeAuto<IntPtr> daip; // expected-error {{different template parameters}} + + // FIXME: It's completely unclear what should happen here. A case can be made + // that 'auto' is more specialized, because it's always a prvalue, whereas + // 'decltype(auto)' could have any value category. Under that interpretation, + // we get the following results entirely backwards: + TAuto<DecltypeAuto> ada; // expected-error {{different template parameters}} + TAutoPtr<DecltypeAuto> apda; // expected-error {{different template parameters}} + TDecltypeAuto<Auto> daa; + TDecltypeAuto<AutoPtr> daa; // expected-error {{different template parameters}} int n; template<auto A, decltype(A) B = &n> struct SubstFailure; diff --git a/tools/clang-fuzzer/ClangFuzzer.cpp b/tools/clang-fuzzer/ClangFuzzer.cpp index afe57d4a666c..1692882c0b5f 100644 --- a/tools/clang-fuzzer/ClangFuzzer.cpp +++ b/tools/clang-fuzzer/ClangFuzzer.cpp @@ -42,7 +42,7 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t *data, size_t size) { tooling::newFrontendActionFactory<clang::SyntaxOnlyAction>()); std::shared_ptr<PCHContainerOperations> PCHContainerOps = std::make_shared<PCHContainerOperations>(); - action->runInvocation(Invocation.release(), Files.get(), PCHContainerOps, + action->runInvocation(std::move(Invocation), Files.get(), PCHContainerOps, &Diags); return 0; } diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index 9cdb2ee8d697..67fa2aea1d45 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -2016,6 +2016,8 @@ public: const OMPTargetTeamsDistributeParallelForDirective *D); void VisitOMPTargetTeamsDistributeParallelForSimdDirective( const OMPTargetTeamsDistributeParallelForSimdDirective *D); + void VisitOMPTargetTeamsDistributeSimdDirective( + const OMPTargetTeamsDistributeSimdDirective *D); private: void AddDeclarationNameInfo(const Stmt *S); @@ -2840,6 +2842,11 @@ void EnqueueVisitor::VisitOMPTargetTeamsDistributeParallelForSimdDirective( VisitOMPLoopDirective(D); } +void EnqueueVisitor::VisitOMPTargetTeamsDistributeSimdDirective( + const OMPTargetTeamsDistributeSimdDirective *D) { + VisitOMPLoopDirective(D); +} + void CursorVisitor::EnqueueWorkList(VisitorWorkList &WL, const Stmt *S) { EnqueueVisitor(WL, MakeCXCursor(S, StmtParent, TU,RegionOfInterest)).Visit(S); } @@ -5011,6 +5018,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) { case CXCursor_OMPTargetTeamsDistributeParallelForSimdDirective: return cxstring::createRef( "OMPTargetTeamsDistributeParallelForSimdDirective"); + case CXCursor_OMPTargetTeamsDistributeSimdDirective: + return cxstring::createRef("OMPTargetTeamsDistributeSimdDirective"); case CXCursor_OverloadCandidate: return cxstring::createRef("OverloadCandidate"); case CXCursor_TypeAliasTemplateDecl: diff --git a/tools/libclang/CXCursor.cpp b/tools/libclang/CXCursor.cpp index e69835a6b1ea..8731ca65c423 100644 --- a/tools/libclang/CXCursor.cpp +++ b/tools/libclang/CXCursor.cpp @@ -679,6 +679,9 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent, case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass: K = CXCursor_OMPTargetTeamsDistributeParallelForSimdDirective; break; + case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass: + K = CXCursor_OMPTargetTeamsDistributeSimdDirective; + break; } CXCursor C = { K, 0, { Parent, S, TU } }; diff --git a/unittests/AST/SourceLocationTest.cpp b/unittests/AST/SourceLocationTest.cpp index add85c366024..5f69c5404361 100644 --- a/unittests/AST/SourceLocationTest.cpp +++ b/unittests/AST/SourceLocationTest.cpp @@ -670,5 +670,72 @@ TEST(CXXMethodDecl, CXXMethodDeclWithNoExceptSpecification) { Language::Lang_CXX11)); } +class ExceptionSpecRangeVerifier : public RangeVerifier<TypeLoc> { +protected: + SourceRange getRange(const TypeLoc &Node) override { + auto T = + Node.getUnqualifiedLoc().castAs<FunctionProtoTypeLoc>(); + assert(!T.isNull()); + return T.getExceptionSpecRange(); + } +}; + +class ParmVarExceptionSpecRangeVerifier : public RangeVerifier<ParmVarDecl> { +protected: + SourceRange getRange(const ParmVarDecl &Node) override { + if (const TypeSourceInfo *TSI = Node.getTypeSourceInfo()) { + TypeLoc TL = TSI->getTypeLoc(); + if (TL.getType()->isPointerType()) { + TL = TL.getNextTypeLoc().IgnoreParens(); + if (auto FPTL = TL.getAs<FunctionProtoTypeLoc>()) { + return FPTL.getExceptionSpecRange(); + } + } + } + return SourceRange(); + } +}; + +TEST(FunctionDecl, ExceptionSpecifications) { + ExceptionSpecRangeVerifier Verifier; + + Verifier.expectRange(1, 10, 1, 16); + EXPECT_TRUE(Verifier.match("void f() throw();\n", loc(functionType()))); + + Verifier.expectRange(1, 10, 1, 34); + EXPECT_TRUE(Verifier.match("void f() throw(void(void) throw());\n", + loc(functionType()))); + + Verifier.expectRange(1, 10, 1, 19); + std::vector<std::string> Args; + Args.push_back("-fms-extensions"); + EXPECT_TRUE(Verifier.match("void f() throw(...);\n", loc(functionType()), + Args, Language::Lang_CXX)); + + Verifier.expectRange(1, 10, 1, 10); + EXPECT_TRUE(Verifier.match("void f() noexcept;\n", loc(functionType()), + Language::Lang_CXX11)); + + Verifier.expectRange(1, 10, 1, 24); + EXPECT_TRUE(Verifier.match("void f() noexcept(false);\n", loc(functionType()), + Language::Lang_CXX11)); + + Verifier.expectRange(1, 10, 1, 32); + EXPECT_TRUE(Verifier.match("void f() noexcept(noexcept(1+1));\n", + loc(functionType()), Language::Lang_CXX11)); + + ParmVarExceptionSpecRangeVerifier Verifier2; + Verifier2.expectRange(1, 25, 1, 31); + EXPECT_TRUE(Verifier2.match("void g(void (*fp)(void) throw());\n", + parmVarDecl(hasType(pointerType(pointee( + parenType(innerType(functionType())))))))); + + Verifier2.expectRange(1, 25, 1, 38); + EXPECT_TRUE(Verifier2.match("void g(void (*fp)(void) noexcept(true));\n", + parmVarDecl(hasType(pointerType(pointee( + parenType(innerType(functionType())))))), + Language::Lang_CXX11)); +} + } // end namespace ast_matchers } // end namespace clang diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp index 629e85803d64..b402b5c4a54c 100644 --- a/unittests/Format/FormatTest.cpp +++ b/unittests/Format/FormatTest.cpp @@ -6816,6 +6816,14 @@ TEST_F(FormatTest, FormatsBracedListsInColumnLayout) { " aaaaaa.aaaaaaa,\n" " aaaaaa.aaaaaaa,\n" "};"); + + // Don't create hanging lists. + verifyFormat("someFunction(Param,\n" + " {List1, List2,\n" + " List3});", + getLLVMStyleWithColumns(35)); + verifyFormat("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaa, {},\n" + " aaaaaaaaaaaaaaaaaaaaaaa);"); } TEST_F(FormatTest, PullTrivialFunctionDefinitionsIntoSingleLine) { diff --git a/www/cxx_dr_status.html b/www/cxx_dr_status.html index e7d2e5f87c9c..73727c014b4e 100644 --- a/www/cxx_dr_status.html +++ b/www/cxx_dr_status.html @@ -28,7 +28,7 @@ <!--*************************************************************************--> <h1>C++ Defect Report Support in Clang</h1> <!--*************************************************************************--> -<p>Last updated: $Date: 2017-01-09 09:01:21 +0100 (Mon, 09 Jan 2017) $</p> +<p>Last updated: $Date: 2017-01-13 17:52:17 +0100 (Fri, 13 Jan 2017) $</p> <h2 id="cxxdr">C++ defect report implementation status</h2> @@ -591,7 +591,7 @@ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#92">92</a></td> <td>WP</td> <td>Should <I>exception-specification</I>s be part of the type system?</td> - <td class="svn" align="center">SVN (C++17 onwards)</td> + <td class="svn" align="center">Clang 4 (C++17 onwards)</td> </tr> <tr id="93"> <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#93">93</a></td> @@ -1594,7 +1594,7 @@ accessible?</td> <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#259">259</a></td> <td>CD1</td> <td>Restrictions on explicit specialization and instantiation</td> - <td class="svn" align="center">SVN</td> + <td class="svn" align="center">Clang 4</td> </tr> <tr class="open" id="260"> <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#260">260</a></td> @@ -3541,7 +3541,7 @@ and <I>POD class</I></td> <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#583">583</a></td> <td>CD3</td> <td>Relational pointer comparisons against the null pointer constant</td> - <td class="svn" align="center">SVN</td> + <td class="svn" align="center">Clang 4</td> </tr> <tr id="584"> <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#584">584</a></td> @@ -3739,7 +3739,7 @@ and <I>POD class</I></td> <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#616">616</a></td> <td>CD3</td> <td>Definition of “indeterminate value”</td> - <td class="svn" align="center">SVN</td> + <td class="svn" align="center">Clang 4</td> </tr> <tr class="open" id="617"> <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#617">617</a></td> @@ -7093,7 +7093,7 @@ and <I>POD class</I></td> <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1213">1213</a></td> <td>CD3</td> <td>Array subscripting and xvalues</td> - <td class="svn" align="center">SVN</td> + <td class="svn" align="center">Clang 4</td> </tr> <tr id="1214"> <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1214">1214</a></td> @@ -7585,7 +7585,7 @@ and <I>POD class</I></td> <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1295">1295</a></td> <td>CD3</td> <td>Binding a reference to an rvalue bit-field</td> - <td class="svn" align="center">SVN</td> + <td class="svn" align="center">Clang 4</td> </tr> <tr id="1296"> <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1296">1296</a></td> @@ -7795,7 +7795,7 @@ and <I>POD class</I></td> <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1330">1330</a></td> <td>CD3</td> <td>Delayed instantiation of <TT>noexcept</TT> specifiers</td> - <td class="svn" align="center">SVN (C++11 onwards)</td> + <td class="svn" align="center">Clang 4 (C++11 onwards)</td> </tr> <tr class="open" id="1331"> <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#1331">1331</a></td> @@ -8143,7 +8143,7 @@ and <I>POD class</I></td> <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1388">1388</a></td> <td>CD3</td> <td>Missing non-deduced context following a function parameter pack</td> - <td class="svn" align="center">SVN</td> + <td class="svn" align="center">Clang 4</td> </tr> <tr id="1389"> <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#1389">1389</a></td> @@ -8785,7 +8785,7 @@ and <I>POD class</I></td> <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1495">1495</a></td> <td>CD3</td> <td>Partial specialization of variadic class template</td> - <td class="svn" align="center">SVN</td> + <td class="svn" align="center">Clang 4</td> </tr> <tr id="1496"> <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1496">1496</a></td> @@ -8887,7 +8887,7 @@ and <I>POD class</I></td> <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1512">1512</a></td> <td>CD3</td> <td>Pointer comparison vs qualification conversions</td> - <td class="svn" align="center">SVN</td> + <td class="svn" align="center">Clang 4</td> </tr> <tr class="open" id="1513"> <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1513">1513</a></td> @@ -8923,7 +8923,7 @@ and <I>POD class</I></td> <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1518">1518</a></td> <td>DRWP</td> <td>Explicit default constructors and copy-list-initialization</td> - <td class="svn" align="center">SVN</td> + <td class="svn" align="center">Clang 4</td> </tr> <tr id="1519"> <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#1519">1519</a></td> @@ -9733,7 +9733,7 @@ and <I>POD class</I></td> <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1653">1653</a></td> <td>WP</td> <td>Removing deprecated increment of <TT>bool</TT></td> - <td class="svn" align="center">SVN (C++17 onwards)</td> + <td class="svn" align="center">Clang 4 (C++17 onwards)</td> </tr> <tr id="1654"> <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#1654">1654</a></td> @@ -11161,7 +11161,7 @@ and <I>POD class</I></td> <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1891">1891</a></td> <td>DRWP</td> <td>Move constructor/assignment for closure class</td> - <td class="svn" align="center">SVN</td> + <td class="svn" align="center">Clang 4</td> </tr> <tr id="1892"> <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1892">1892</a></td> diff --git a/www/cxx_status.html b/www/cxx_status.html index c1dc78cf56b0..e55f45fffe5c 100644 --- a/www/cxx_status.html +++ b/www/cxx_status.html @@ -25,7 +25,7 @@ <!--*************************************************************************--> <h1>C++ Support in Clang</h1> <!--*************************************************************************--> -<p>Last updated: $Date: 2016-12-31 22:41:23 +0100 (Sat, 31 Dec 2016) $</p> +<p>Last updated: $Date: 2017-01-13 17:52:17 +0100 (Fri, 13 Jan 2017) $</p> <p>Clang fully implements all published ISO C++ standards (<a href="#cxx98">C++98 / C++03</a>, <a @@ -612,7 +612,7 @@ as the draft C++1z standard evolves. <tr> <td>Make exception specifications part of the type system</td> <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0012r1.html">P0012R1</a></td> - <td class="svn" align="center">SVN</td> + <td class="svn" align="center">Clang 4</td> </tr> <tr> <td><tt>__has_include</tt> in preprocessor conditionals</td> @@ -679,7 +679,7 @@ as the draft C++1z standard evolves. <tr> <td>Dynamic memory allocation for over-aligned data</td> <td><a href="http://wg21.link/p0035r4">P0035R4</a></td> - <td class="svn" align="center">SVN</td> + <td class="svn" align="center">Clang 4</td> </tr> <tr> <td>Template argument deduction for class templates</td> @@ -689,17 +689,17 @@ as the draft C++1z standard evolves. <tr> <td>Non-type template parameters with <tt>auto</tt> type</td> <td><a href="http://wg21.link/p0127r2">P0127R2</a></td> - <td class="svn" align="center">SVN</td> + <td class="svn" align="center">Clang 4</td> </tr> <tr> <td>Guaranteed copy elision</td> <td><a href="http://wg21.link/p0135r1">P0135R1</a></td> - <td class="svn" align="center">SVN</td> + <td class="svn" align="center">Clang 4</td> </tr> <tr> <td rowspan=2>Stricter expression evaluation order</td> <td><a href="http://wg21.link/p0145r3">P0145R3</a></td> - <td class="svn" align="center" rowspan=2>SVN <a href="#p0145">(10)</a></td> + <td class="svn" align="center" rowspan=2>Clang 4 <a href="#p0145">(10)</a></td> </tr> <tr> <td><a href="http://wg21.link/p0400r0">P0400R0</a></td> @@ -722,7 +722,7 @@ as the draft C++1z standard evolves. <tr> <td>Structured bindings</td> <td><a href="http://wg21.link/p0217r3">P0217R3</a></td> - <td class="svn" align="center">SVN</td> + <td class="svn" align="center">Clang 4</td> </tr> <tr> <td>Separate variable and condition for <tt>if</tt> and <tt>switch</tt></td> @@ -738,12 +738,12 @@ as the draft C++1z standard evolves. <tr> <td>Removing deprecated dynamic exception specifications</td> <td><a href="http://wg21.link/p0003r5">P0003R5</a></td> - <td class="svn" align="center">SVN</td> + <td class="svn" align="center">Clang 4</td> </tr> <tr> <td>Pack expansions in <em>using-declarations</em></td> <td><a href="http://wg21.link/p0195r2">P0195R2</a></td> - <td class="svn" align="center">SVN</td> + <td class="svn" align="center">Clang 4</td> </tr> </table> @@ -765,10 +765,10 @@ reverse construction order in that ABI. </span><br> <span id="p0522">(12): Despite being the the resolution to a Defect Report, this feature is disabled by default in all language versions, and can be enabled -explicitly with the flag <tt>-frelaxed-template-template-args</tt>. The change -to the standard lacks a corresponding change for template partial ordering, -resulting in ambiguity errors for reasonable and previously-valid code. This -issue is expected to be rectified soon. +explicitly with the flag <tt>-frelaxed-template-template-args</tt> in Clang 4. +The change to the standard lacks a corresponding change for template partial +ordering, resulting in ambiguity errors for reasonable and previously-valid +code. This issue is expected to be rectified soon. </span> </p> </details> @@ -802,8 +802,8 @@ and library features that are not part of standard C++.</p> </td> </tr> <tr> - <td class="svn" align="center"> - SVN (<a href="http://wg21.link/p0096r3">P0096R3</a>)</a> + <td class="full" align="center"> + Clang 4 (<a href="http://wg21.link/p0096r3">P0096R3</a>)</a> </td> </tr> <!-- FIXME: Implement latest recommendations. diff --git a/www/index.html b/www/index.html index 62354fe60c86..9a4050121d82 100644 --- a/www/index.html +++ b/www/index.html @@ -15,10 +15,10 @@ <h1>clang: a C language family frontend for LLVM</h1> <!--*********************************************************************--> - <p>The goal of the Clang project is to create a new C, C++, Objective C and - Objective C++ front-end for the <a href="http://www.llvm.org/">LLVM</a> - compiler. You can <a href="get_started.html">get and build</a> the source - today.</p> + <p>The goal of the Clang project is to create a new C based language + front-end: C, C++, Objective C/C++, OpenCL C and others for the + <a href="http://www.llvm.org/">LLVM</a> compiler. You can + <a href="get_started.html">get and build</a> the source today.</p> <!--=====================================================================--> <h2 id="goals">Features and Goals</h2> diff --git a/www/make_cxx_dr_status b/www/make_cxx_dr_status index 48f524208a4c..8a05d41c08b5 100755 --- a/www/make_cxx_dr_status +++ b/www/make_cxx_dr_status @@ -108,10 +108,13 @@ def availability(issue): if status == 'unknown': avail = 'Unknown' avail_style = ' class="none"' - elif status == '4.0': + elif status == '5': avail = 'SVN' avail_style = ' class="svn"' - elif re.match('^[0-9]+\.', status): + elif status == '4': + avail = 'Clang 4' + avail_style = ' class="svn"' + elif re.match('^[0-9]+\.?[0-9]*', status): avail = 'Clang %s' % status avail_style = ' class="full"' elif status == 'yes': |