Vendor import of clang release_40 branch r292009:
https://llvm.org/svn/llvm-project/cfe/branches/release_40@292009
This commit is contained in:
parent
fdc82ccb3f
commit
d2e0a8dd94
@ -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}")
|
||||
|
@ -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
|
||||
|
@ -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'
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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 ....
|
||||
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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!");
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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 *); }
|
||||
|
@ -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)
|
||||
|
@ -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<
|
||||
|
@ -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
|
||||
|
@ -244,3 +244,4 @@ def OMPTargetTeamsDirective : DStmt<OMPExecutableDirective>;
|
||||
def OMPTargetTeamsDistributeDirective : DStmt<OMPLoopDirective>;
|
||||
def OMPTargetTeamsDistributeParallelForDirective : DStmt<OMPLoopDirective>;
|
||||
def OMPTargetTeamsDistributeParallelForSimdDirective : DStmt<OMPLoopDirective>;
|
||||
def OMPTargetTeamsDistributeSimdDirective : DStmt<OMPLoopDirective>;
|
||||
|
@ -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">;
|
||||
|
@ -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>;
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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());
|
||||
|
@ -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()) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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())
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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(
|
||||
|
@ -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;
|
||||
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);
|
||||
|
||||
// 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".
|
||||
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".
|
||||
CFGBlock *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)
|
||||
|
@ -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;
|
||||
|
@ -695,6 +695,16 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind,
|
||||
#define OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(Name) \
|
||||
case OMPC_##Name: \
|
||||
return true;
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
default:
|
||||
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;
|
||||
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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"));
|
||||
|
@ -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) {
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -330,6 +330,10 @@ void CodeGenFunction::EmitStmt(const Stmt *S) {
|
||||
EmitOMPTargetTeamsDistributeParallelForSimdDirective(
|
||||
cast<OMPTargetTeamsDistributeParallelForSimdDirective>(*S));
|
||||
break;
|
||||
case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
|
||||
EmitOMPTargetTeamsDistributeSimdDirective(
|
||||
cast<OMPTargetTeamsDistributeSimdDirective>(*S));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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*/,
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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"};
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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()));
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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(),
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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,34 +6601,41 @@ static SourceLocation getCaptureLocation(const LambdaScopeInfo *LSI,
|
||||
return SourceLocation();
|
||||
}
|
||||
|
||||
/// \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 nullptr;
|
||||
|
||||
// Don't diagnose declarations at file scope.
|
||||
if (D->hasGlobalStorage())
|
||||
return nullptr;
|
||||
|
||||
// Only diagnose if we're shadowing an unambiguous field or variable.
|
||||
if (R.getResultKind() != LookupResult::Found)
|
||||
return nullptr;
|
||||
|
||||
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 S the scope in which the shadowing name is being declared
|
||||
/// \param ShadowedDecl the declaration that is shadowed by the given variable
|
||||
/// \param R the lookup of the name
|
||||
///
|
||||
void Sema::CheckShadow(Scope *S, VarDecl *D, const LookupResult& R) {
|
||||
// Return if warning is ignored.
|
||||
if (Diags.isIgnored(diag::warn_decl_shadow, R.getNameLoc()))
|
||||
return;
|
||||
|
||||
// Don't diagnose declarations at file scope.
|
||||
if (D->hasGlobalStorage())
|
||||
return;
|
||||
|
||||
void Sema::CheckShadow(VarDecl *D, NamedDecl *ShadowedDecl,
|
||||
const LookupResult &R) {
|
||||
DeclContext *NewDC = D->getDeclContext();
|
||||
|
||||
// Only diagnose if we're shadowing an unambiguous field or variable.
|
||||
if (R.getResultKind() != LookupResult::Found)
|
||||
return;
|
||||
|
||||
NamedDecl* ShadowedDecl = R.getFoundDecl();
|
||||
if (!isa<VarDecl>(ShadowedDecl) && !isa<FieldDecl>(ShadowedDecl))
|
||||
return;
|
||||
|
||||
if (FieldDecl *FD = dyn_cast<FieldDecl>(ShadowedDecl)) {
|
||||
// Fields are not shadowed by variables in C++ static methods.
|
||||
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewDC))
|
||||
@ -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()) {
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
} else {
|
||||
// Builtin binary operator with a bad first conversion.
|
||||
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.
|
||||
!isa<CXXConstructorDecl>(Cand->Function)) {
|
||||
// Conversion 0 is 'this', which doesn't have a corresponding argument.
|
||||
ConvIdx = 1;
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
// Builtin operator.
|
||||
assert(ConvCount <= 3);
|
||||
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=*/
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
|
@ -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()));
|
||||
|
@ -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;
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -197,3 +197,10 @@ namespace ReferenceInitialization {
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
namespace PR31592 {
|
||||
struct C {
|
||||
C() : f("}") { } // no-crash
|
||||
const char(&f)[2];
|
||||
};
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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.
|
||||
//------
|
||||
|
21
test/CXX/basic/basic.start/basic.start.init/p2.cpp
Normal file
21
test/CXX/basic/basic.start/basic.start.init/p2.cpp
Normal file
@ -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};
|
@ -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
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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}}
|
||||
|
@ -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}}
|
||||
|
@ -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}}
|
||||
|
@ -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++;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user