aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-07-01 13:24:05 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-07-01 13:24:05 +0000
commitcf1b401909b5e54edfd80656b1a18eaa31f9f6f1 (patch)
treeedb0ffff2a43d84ba9b4c862b394cfeeebb36ddc
parentef915aab0ac566c55bfb0d7a9f6635bb5d94d4af (diff)
downloadsrc-cf1b401909b5e54edfd80656b1a18eaa31f9f6f1.tar.gz
src-cf1b401909b5e54edfd80656b1a18eaa31f9f6f1.zip
Vendor import of clang trunk r306956:vendor/clang/clang-trunk-r306956
Notes
Notes: svn path=/vendor/clang/dist/; revision=320535 svn path=/vendor/clang/clang-trunk-r306956/; revision=320536; tag=vendor/clang/clang-trunk-r306956
-rw-r--r--bindings/python/clang/cindex.py44
-rw-r--r--bindings/python/tests/test_exception_specification_kind.py27
-rw-r--r--docs/UsersManual.rst40
-rw-r--r--include/clang-c/Index.h69
-rw-r--r--include/clang/AST/ASTContext.h5
-rw-r--r--include/clang/AST/ASTStructuralEquivalence.h6
-rw-r--r--include/clang/AST/Decl.h5
-rw-r--r--include/clang/AST/NSAPI.h4
-rw-r--r--include/clang/AST/OpenMPClause.h3
-rw-r--r--include/clang/AST/RecursiveASTVisitor.h18
-rw-r--r--include/clang/AST/Redeclarable.h54
-rw-r--r--include/clang/Basic/AttrDocs.td40
-rw-r--r--include/clang/Basic/BuiltinsNios2.def70
-rw-r--r--include/clang/Basic/BuiltinsWebAssembly.def4
-rw-r--r--include/clang/Basic/DiagnosticASTKinds.td11
-rw-r--r--include/clang/Basic/DiagnosticDriverKinds.td7
-rw-r--r--include/clang/Basic/DiagnosticGroups.td1
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td18
-rw-r--r--include/clang/Basic/LangOptions.def1
-rw-r--r--include/clang/Basic/OpenMPKinds.def2
-rw-r--r--include/clang/Basic/SourceLocation.h122
-rw-r--r--include/clang/Basic/SourceManager.h61
-rw-r--r--include/clang/Basic/TargetBuiltins.h10
-rw-r--r--include/clang/Basic/TargetOptions.h3
-rw-r--r--include/clang/Basic/Visibility.h3
-rw-r--r--include/clang/Driver/CC1Options.td11
-rw-r--r--include/clang/Driver/Compilation.h8
-rw-r--r--include/clang/Driver/Driver.h3
-rw-r--r--include/clang/Driver/Options.td6
-rw-r--r--include/clang/Format/Format.h26
-rw-r--r--include/clang/Frontend/ASTUnit.h11
-rw-r--r--include/clang/Frontend/CodeGenOptions.def7
-rw-r--r--include/clang/Frontend/DiagnosticRenderer.h83
-rw-r--r--include/clang/Frontend/TextDiagnostic.h43
-rw-r--r--include/clang/Frontend/Utils.h9
-rw-r--r--include/clang/Lex/HeaderSearch.h2
-rw-r--r--include/clang/Lex/PTHLexer.h2
-rw-r--r--include/clang/Sema/Lookup.h8
-rw-r--r--include/clang/Sema/Sema.h37
-rw-r--r--include/clang/Serialization/ASTReader.h18
-rw-r--r--include/clang/StaticAnalyzer/Checkers/Checkers.td18
-rw-r--r--include/clang/Tooling/Refactoring/Rename/RenamingAction.h70
-rw-r--r--include/clang/Tooling/Refactoring/Rename/USRFinder.h84
-rw-r--r--include/clang/Tooling/Refactoring/Rename/USRFindingAction.h54
-rw-r--r--include/clang/Tooling/Refactoring/Rename/USRLocFinder.h49
-rw-r--r--include/clang/module.modulemap4
-rw-r--r--lib/AST/ASTContext.cpp16
-rw-r--r--lib/AST/ASTStructuralEquivalence.cpp58
-rw-r--r--lib/AST/Decl.cpp11
-rw-r--r--lib/AST/DeclCXX.cpp5
-rw-r--r--lib/AST/Expr.cpp29
-rw-r--r--lib/AST/ExprConstant.cpp13
-rw-r--r--lib/AST/MicrosoftMangle.cpp75
-rw-r--r--lib/AST/ODRHash.cpp45
-rw-r--r--lib/AST/RecordLayoutBuilder.cpp35
-rw-r--r--lib/AST/StmtProfile.cpp5
-rw-r--r--lib/Basic/SourceLocation.cpp70
-rw-r--r--lib/Basic/SourceManager.cpp85
-rw-r--r--lib/Basic/Targets.cpp283
-rw-r--r--lib/CodeGen/BackendUtil.cpp38
-rw-r--r--lib/CodeGen/CGBuiltin.cpp10
-rw-r--r--lib/CodeGen/CGCall.cpp14
-rw-r--r--lib/CodeGen/CGDecl.cpp4
-rw-r--r--lib/CodeGen/CGObjCMac.cpp44
-rw-r--r--lib/CodeGen/CGObjCRuntime.cpp51
-rw-r--r--lib/CodeGen/CGOpenMPRuntime.cpp20
-rw-r--r--lib/CodeGen/CGStmtOpenMP.cpp203
-rw-r--r--lib/CodeGen/CodeGenAction.cpp7
-rw-r--r--lib/CodeGen/CodeGenPGO.cpp3
-rw-r--r--lib/Driver/Compilation.cpp5
-rw-r--r--lib/Driver/Driver.cpp42
-rw-r--r--lib/Driver/SanitizerArgs.cpp2
-rw-r--r--lib/Driver/ToolChains/Arch/ARM.cpp4
-rw-r--r--lib/Driver/ToolChains/Clang.cpp90
-rw-r--r--lib/Driver/ToolChains/CommonArgs.cpp22
-rw-r--r--lib/Driver/ToolChains/CrossWindows.cpp14
-rw-r--r--lib/Driver/ToolChains/Darwin.cpp52
-rw-r--r--lib/Driver/ToolChains/Darwin.h8
-rw-r--r--lib/Driver/ToolChains/MipsLinux.cpp2
-rw-r--r--lib/Format/ContinuationIndenter.cpp24
-rw-r--r--lib/Format/Format.cpp29
-rw-r--r--lib/Format/FormatToken.h16
-rw-r--r--lib/Format/NamespaceEndCommentsFixer.cpp2
-rw-r--r--lib/Format/TokenAnnotator.cpp31
-rw-r--r--lib/Format/UnwrappedLineFormatter.cpp28
-rw-r--r--lib/Format/UnwrappedLineParser.cpp17
-rw-r--r--lib/Format/UnwrappedLineParser.h3
-rw-r--r--lib/Frontend/ASTMerge.cpp6
-rw-r--r--lib/Frontend/ASTUnit.cpp45
-rw-r--r--lib/Frontend/ChainedIncludesSource.cpp2
-rw-r--r--lib/Frontend/CompilerInstance.cpp16
-rw-r--r--lib/Frontend/CompilerInvocation.cpp29
-rw-r--r--lib/Frontend/CreateInvocationFromCommandLine.cpp6
-rw-r--r--lib/Frontend/DependencyFile.cpp6
-rw-r--r--lib/Frontend/DiagnosticRenderer.cpp196
-rw-r--r--lib/Frontend/FrontendAction.cpp51
-rw-r--r--lib/Frontend/FrontendActions.cpp2
-rw-r--r--lib/Frontend/InitPreprocessor.cpp2
-rw-r--r--lib/Frontend/ModuleDependencyCollector.cpp2
-rw-r--r--lib/Frontend/SerializedDiagnosticPrinter.cpp106
-rw-r--r--lib/Frontend/TextDiagnostic.cpp85
-rw-r--r--lib/Frontend/TextDiagnosticPrinter.cpp7
-rw-r--r--lib/Lex/ModuleMap.cpp3
-rw-r--r--lib/Lex/PPMacroExpansion.cpp2
-rw-r--r--lib/Parse/ParseDecl.cpp35
-rw-r--r--lib/Parse/ParseDeclCXX.cpp16
-rw-r--r--lib/Sema/AnalysisBasedWarnings.cpp6
-rw-r--r--lib/Sema/Sema.cpp5
-rw-r--r--lib/Sema/SemaChecking.cpp25
-rw-r--r--lib/Sema/SemaDecl.cpp182
-rw-r--r--lib/Sema/SemaDeclAttr.cpp2
-rw-r--r--lib/Sema/SemaDeclCXX.cpp9
-rw-r--r--lib/Sema/SemaExprCXX.cpp46
-rw-r--r--lib/Sema/SemaOpenMP.cpp29
-rw-r--r--lib/Sema/SemaType.cpp15
-rw-r--r--lib/Serialization/ASTReader.cpp158
-rw-r--r--lib/Serialization/ASTReaderDecl.cpp171
-rw-r--r--lib/Serialization/ASTReaderStmt.cpp1
-rw-r--r--lib/Serialization/ASTWriter.cpp18
-rw-r--r--lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp55
-rw-r--r--lib/Tooling/CompilationDatabase.cpp8
-rw-r--r--lib/Tooling/Refactoring/AtomicChange.cpp1
-rw-r--r--lib/Tooling/Refactoring/CMakeLists.txt8
-rw-r--r--lib/Tooling/Refactoring/Rename/RenamingAction.cpp134
-rw-r--r--lib/Tooling/Refactoring/Rename/USRFinder.cpp213
-rw-r--r--lib/Tooling/Refactoring/Rename/USRFindingAction.cpp236
-rw-r--r--lib/Tooling/Refactoring/Rename/USRLocFinder.cpp509
-rw-r--r--test/Analysis/malloc-overflow2.c6
-rw-r--r--test/Analysis/unix-fns.c4
-rw-r--r--test/CMakeLists.txt1
-rw-r--r--test/CodeGen/arm-execute-only.c78
-rw-r--r--test/CodeGen/arm-v8.1a-neon-intrinsics.c2
-rw-r--r--test/CodeGen/avx512f-builtins.c27
-rw-r--r--test/CodeGen/builtins-wasm.c12
-rw-r--r--test/CodeGen/lto-newpm-pipeline.c53
-rw-r--r--test/CodeGen/mangle-ms.c9
-rw-r--r--test/CodeGen/mangle.c4
-rw-r--r--test/CodeGen/named_reg_global.c2
-rw-r--r--test/CodeGen/neon-immediate-ubsan.c2
-rw-r--r--test/CodeGen/pgo-sample-thinlto-summary.c26
-rw-r--r--test/CodeGen/xray-attributes-supported.cpp2
-rw-r--r--test/CodeGenCXX/dllexport-dtor-thunks.cpp10
-rw-r--r--test/CodeGenCXX/mangle-ms.cpp7
-rw-r--r--test/CodeGenCXX/msabi-blocks.cpp113
-rw-r--r--test/CodeGenObjC/ivar-type-encoding.m16
-rw-r--r--test/CodeGenObjC/parameterized_classes.m28
-rw-r--r--test/CodeGenObjC/protocol-comdat.m8
-rw-r--r--test/CodeGenObjC/stret-1.m11
-rw-r--r--test/CodeGenObjC/stret-lifetime.m34
-rw-r--r--test/CodeGenObjCXX/arc-indirect.mm22
-rw-r--r--test/CodeGenOpenCL/addr-space-struct-arg.cl52
-rw-r--r--test/Driver/arm-execute-only.c72
-rw-r--r--test/Driver/clang_f_opts.c7
-rw-r--r--test/Driver/darwin-version.c35
-rw-r--r--test/Driver/fuzzer.c8
-rw-r--r--test/Driver/nios2-cpu.c26
-rw-r--r--test/Driver/openmp-offload.c64
-rw-r--r--test/Driver/unavailable_aligned_allocation.cpp54
-rw-r--r--test/Driver/windows-cross.c5
-rw-r--r--test/FixIt/fixit-format-darwin.m10
-rw-r--r--test/FixIt/format-darwin.m23
-rw-r--r--test/Frontend/Inputs/optimization-remark-with-hotness-sample.proftext2
-rw-r--r--test/Frontend/optimization-remark-with-hotness.c20
-rw-r--r--test/Index/ctor-init-source-loc.cpp117
-rw-r--r--test/Index/get-cursor.cpp17
-rw-r--r--test/Index/linkage.c2
-rw-r--r--test/Modules/Inputs/F.framework/Headers/F.h1
-rw-r--r--test/Modules/Inputs/F.framework/Modules/module.modulemap7
-rw-r--r--test/Modules/Inputs/F.framework/Modules/module.private.modulemap7
-rw-r--r--test/Modules/Inputs/F.framework/PrivateHeaders/NS.h19
-rw-r--r--test/Modules/Inputs/lookup-assert-protocol/Base.h3
-rw-r--r--test/Modules/Inputs/lookup-assert-protocol/Derive.h4
-rw-r--r--test/Modules/Inputs/lookup-assert-protocol/H3.h1
-rw-r--r--test/Modules/Inputs/lookup-assert-protocol/module.map4
-rw-r--r--test/Modules/Inputs/preprocess-decluse/a.h1
-rw-r--r--test/Modules/Inputs/preprocess-decluse/a.modulemap1
-rw-r--r--test/Modules/Inputs/preprocess-decluse/b.h1
-rw-r--r--test/Modules/Inputs/preprocess-decluse/b.modulemap1
-rw-r--r--test/Modules/Inputs/preprocess-decluse/main.modulemap1
-rw-r--r--test/Modules/diag-flags.cpp2
-rw-r--r--test/Modules/elaborated-type-specifier-from-hidden-module.m7
-rw-r--r--test/Modules/lookup-assert-protocol.m17
-rw-r--r--test/Modules/odr_hash.cpp68
-rw-r--r--test/Modules/preprocess-decluse.cpp18
-rw-r--r--test/Modules/redefinition-c-tagtypes.m48
-rw-r--r--test/Modules/redefinition-same-header.m10
-rw-r--r--test/OpenMP/parallel_codegen.cpp4
-rw-r--r--test/OpenMP/target_codegen.cpp283
-rw-r--r--test/OpenMP/target_codegen_global_capture.cpp143
-rw-r--r--test/OpenMP/target_data_codegen.cpp51
-rw-r--r--test/OpenMP/target_data_use_device_ptr_codegen.cpp113
-rw-r--r--test/OpenMP/target_enter_data_codegen.cpp51
-rw-r--r--test/OpenMP/target_exit_data_codegen.cpp51
-rw-r--r--test/OpenMP/target_firstprivate_codegen.cpp160
-rw-r--r--test/OpenMP/target_is_device_ptr_codegen.cpp112
-rw-r--r--test/OpenMP/target_map_codegen.cpp1626
-rw-r--r--test/OpenMP/target_parallel_codegen.cpp186
-rw-r--r--test/OpenMP/target_teams_codegen.cpp186
-rw-r--r--test/OpenMP/target_update_codegen.cpp53
-rw-r--r--test/OpenMP/taskloop_ast_print.cpp16
-rw-r--r--test/OpenMP/taskloop_simd_ast_print.cpp16
-rw-r--r--test/PCH/attrs.c3
-rw-r--r--test/Preprocessor/aarch64-target-features.c5
-rw-r--r--test/Preprocessor/arm-target-features.c1
-rw-r--r--test/Preprocessor/predefined-arch-macros.c75
-rw-r--r--test/Preprocessor/predefined-macros.c6
-rw-r--r--test/Profile/Inputs/cxx-missing-bodies.proftext9
-rw-r--r--test/Profile/cxx-missing-bodies.cpp21
-rw-r--r--test/Profile/cxx-structors.cpp2
-rw-r--r--test/Sema/diagnose_if.c4
-rw-r--r--test/Sema/integer-overflow.c8
-rw-r--r--test/Sema/overloadable.c100
-rw-r--r--test/SemaCXX/constant-expression-cxx11.cpp16
-rw-r--r--test/SemaCXX/eval-crashes.cpp56
-rw-r--r--test/SemaCXX/type-traits.cpp25
-rw-r--r--test/SemaCXX/unavailable_aligned_allocation.cpp109
-rw-r--r--test/SemaCXX/warn-throw-out-noexcept-func.cpp37
-rw-r--r--test/SemaOpenCL/extension-begin.cl2
-rw-r--r--test/SemaTemplate/destructor-template.cpp6
-rw-r--r--test/clang-rename/ClassAsTemplateArgument.cpp21
-rw-r--r--test/clang-rename/ClassFindByName.cpp10
-rw-r--r--test/clang-rename/ClassSimpleRenaming.cpp14
-rw-r--r--test/clang-rename/ClassTestMulti.cpp11
-rw-r--r--test/clang-rename/ClassTestMultiByName.cpp8
-rw-r--r--test/clang-rename/ComplexFunctionOverride.cpp47
-rw-r--r--test/clang-rename/ComplicatedClassType.cpp63
-rw-r--r--test/clang-rename/Ctor.cpp14
-rw-r--r--test/clang-rename/CtorInitializer.cpp17
-rw-r--r--test/clang-rename/DeclRefExpr.cpp24
-rw-r--r--test/clang-rename/Field.cpp15
-rw-r--r--test/clang-rename/FunctionMacro.cpp20
-rw-r--r--test/clang-rename/FunctionOverride.cpp13
-rw-r--r--test/clang-rename/FunctionWithClassFindByName.cpp12
-rw-r--r--test/clang-rename/IncludeHeaderWithSymbol.cpp10
-rw-r--r--test/clang-rename/Inputs/HeaderWithSymbol.h1
-rw-r--r--test/clang-rename/Inputs/OffsetToNewName.yaml6
-rw-r--r--test/clang-rename/Inputs/QualifiedNameToNewName.yaml6
-rw-r--r--test/clang-rename/InvalidNewName.cpp2
-rw-r--r--test/clang-rename/InvalidOffset.cpp9
-rw-r--r--test/clang-rename/InvalidQualifiedName.cpp4
-rw-r--r--test/clang-rename/MemberExprMacro.cpp22
-rw-r--r--test/clang-rename/Namespace.cpp13
-rw-r--r--test/clang-rename/NoNewName.cpp4
-rw-r--r--test/clang-rename/TemplateClassInstantiation.cpp42
-rw-r--r--test/clang-rename/TemplateTypename.cpp24
-rw-r--r--test/clang-rename/TemplatedClassFunction.cpp22
-rw-r--r--test/clang-rename/UserDefinedConversion.cpp26
-rw-r--r--test/clang-rename/Variable.cpp33
-rw-r--r--test/clang-rename/VariableMacro.cpp21
-rw-r--r--test/clang-rename/YAMLInput.cpp10
-rw-r--r--tools/CMakeLists.txt2
-rw-r--r--tools/c-index-test/c-index-test.c31
-rw-r--r--tools/c-index-test/core_main.cpp2
-rw-r--r--tools/clang-rename/CMakeLists.txt24
-rw-r--r--tools/clang-rename/ClangRename.cpp239
-rw-r--r--tools/clang-rename/clang-rename.el79
-rw-r--r--tools/clang-rename/clang-rename.py61
-rw-r--r--tools/driver/driver.cpp2
-rw-r--r--tools/libclang/CIndex.cpp3
-rw-r--r--tools/libclang/CIndexDiagnostic.cpp30
-rw-r--r--tools/libclang/CXType.cpp18
-rw-r--r--tools/libclang/libclang.exports2
-rw-r--r--unittests/CMakeLists.txt1
-rw-r--r--unittests/Driver/ToolChainTest.cpp11
-rw-r--r--unittests/Format/FormatTest.cpp204
-rw-r--r--unittests/Format/FormatTestJava.cpp5
-rw-r--r--unittests/Format/FormatTestProto.cpp172
-rw-r--r--unittests/Format/SortIncludesTest.cpp23
-rw-r--r--unittests/Rename/CMakeLists.txt22
-rw-r--r--unittests/Rename/ClangRenameTest.h112
-rw-r--r--unittests/Rename/RenameClassTest.cpp684
-rw-r--r--unittests/Tooling/CMakeLists.txt1
-rw-r--r--unittests/Tooling/CastExprTest.cpp38
-rw-r--r--unittests/Tooling/CompilationDatabaseTest.cpp21
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTest.cpp86
-rw-r--r--unittests/Tooling/RefactoringTest.cpp12
-rw-r--r--unittests/Tooling/TestVisitor.h5
-rwxr-xr-xutils/bash-autocomplete.sh11
278 files changed, 9540 insertions, 2797 deletions
diff --git a/bindings/python/clang/cindex.py b/bindings/python/clang/cindex.py
index 8440b0aabe08..5e70bde770f8 100644
--- a/bindings/python/clang/cindex.py
+++ b/bindings/python/clang/cindex.py
@@ -1367,6 +1367,30 @@ TemplateArgumentKind.DECLARATION = TemplateArgumentKind(2)
TemplateArgumentKind.NULLPTR = TemplateArgumentKind(3)
TemplateArgumentKind.INTEGRAL = TemplateArgumentKind(4)
+### Exception Specification Kinds ###
+class ExceptionSpecificationKind(BaseEnumeration):
+ """
+ An ExceptionSpecificationKind describes the kind of exception specification
+ that a function has.
+ """
+
+ # The required BaseEnumeration declarations.
+ _kinds = []
+ _name_map = None
+
+ def __repr__(self):
+ return 'ExceptionSpecificationKind.{}'.format(self.name)
+
+ExceptionSpecificationKind.NONE = ExceptionSpecificationKind(0)
+ExceptionSpecificationKind.DYNAMIC_NONE = ExceptionSpecificationKind(1)
+ExceptionSpecificationKind.DYNAMIC = ExceptionSpecificationKind(2)
+ExceptionSpecificationKind.MS_ANY = ExceptionSpecificationKind(3)
+ExceptionSpecificationKind.BASIC_NOEXCEPT = ExceptionSpecificationKind(4)
+ExceptionSpecificationKind.COMPUTED_NOEXCEPT = ExceptionSpecificationKind(5)
+ExceptionSpecificationKind.UNEVALUATED = ExceptionSpecificationKind(6)
+ExceptionSpecificationKind.UNINSTANTIATED = ExceptionSpecificationKind(7)
+ExceptionSpecificationKind.UNPARSED = ExceptionSpecificationKind(8)
+
### Cursors ###
class Cursor(Structure):
@@ -1587,6 +1611,18 @@ class Cursor(Structure):
return self._result_type
@property
+ def exception_specification_kind(self):
+ '''
+ Retrieve the exception specification kind, which is one of the values
+ from the ExceptionSpecificationKind enumeration.
+ '''
+ if not hasattr(self, '_exception_specification_kind'):
+ exc_kind = conf.lib.clang_getCursorExceptionSpecificationType(self)
+ self._exception_specification_kind = ExceptionSpecificationKind.from_id(exc_kind)
+
+ return self._exception_specification_kind
+
+ @property
def underlying_typedef_type(self):
"""Return the underlying type of a typedef declaration.
@@ -2254,6 +2290,14 @@ class Type(Structure):
callbacks['fields_visit'](visitor), fields)
return iter(fields)
+ def get_exception_specification_kind(self):
+ """
+ Return the kind of the exception specification; a value from
+ the ExceptionSpecificationKind enumeration.
+ """
+ return ExceptionSpecificationKind.from_id(
+ conf.lib.clang.getExceptionSpecificationType(self))
+
@property
def spelling(self):
"""Retrieve the spelling of this Type."""
diff --git a/bindings/python/tests/test_exception_specification_kind.py b/bindings/python/tests/test_exception_specification_kind.py
new file mode 100644
index 000000000000..543d47f7db97
--- /dev/null
+++ b/bindings/python/tests/test_exception_specification_kind.py
@@ -0,0 +1,27 @@
+import clang.cindex
+from clang.cindex import ExceptionSpecificationKind
+from .util import get_tu
+
+
+def find_function_declarations(node, declarations=[]):
+ if node.kind == clang.cindex.CursorKind.FUNCTION_DECL:
+ declarations.append((node.spelling, node.exception_specification_kind))
+ for child in node.get_children():
+ declarations = find_function_declarations(child, declarations)
+ return declarations
+
+
+def test_exception_specification_kind():
+ source = """int square1(int x);
+ int square2(int x) noexcept;
+ int square3(int x) noexcept(noexcept(x * x));"""
+
+ tu = get_tu(source, lang='cpp', flags=['-std=c++14'])
+
+ declarations = find_function_declarations(tu.cursor)
+ expected = [
+ ('square1', ExceptionSpecificationKind.NONE),
+ ('square2', ExceptionSpecificationKind.BASIC_NOEXCEPT),
+ ('square3', ExceptionSpecificationKind.COMPUTED_NOEXCEPT)
+ ]
+ assert declarations == expected
diff --git a/docs/UsersManual.rst b/docs/UsersManual.rst
index 7362456202ba..df6344af9102 100644
--- a/docs/UsersManual.rst
+++ b/docs/UsersManual.rst
@@ -322,18 +322,27 @@ output format of the diagnostics that it generates.
by category, so it should be a high level category. We want dozens
of these, not hundreds or thousands of them.
+.. _opt_fsave-optimization-record:
+
+**-fsave-optimization-record**
+ Write optimization remarks to a YAML file.
+
+ This option, which defaults to off, controls whether Clang writes
+ optimization reports to a YAML file. By recording diagnostics in a file,
+ using a structured YAML format, users can parse or sort the remarks in a
+ convenient way.
+
.. _opt_fdiagnostics-show-hotness:
**-f[no-]diagnostics-show-hotness**
Enable profile hotness information in diagnostic line.
- This option, which defaults to off, controls whether Clang prints the
- profile hotness associated with a diagnostics in the presence of
- profile-guided optimization information. This is currently supported with
- optimization remarks (see :ref:`Options to Emit Optimization Reports
- <rpass>`). The hotness information allows users to focus on the hot
- optimization remarks that are likely to be more relevant for run-time
- performance.
+ This option controls whether Clang prints the profile hotness associated
+ with diagnostics in the presence of profile-guided optimization information.
+ This is currently supported with optimization remarks (see
+ :ref:`Options to Emit Optimization Reports <rpass>`). The hotness information
+ allows users to focus on the hot optimization remarks that are likely to be
+ more relevant for run-time performance.
For example, in this output, the block containing the callsite of `foo` was
executed 3000 times according to the profile data:
@@ -344,6 +353,23 @@ output format of the diagnostics that it generates.
sum += foo(x, x - 2);
^
+ This option is implied when
+ :ref:`-fsave-optimization-record <opt_fsave-optimization-record>` is used.
+ Otherwise, it defaults to off.
+
+.. _opt_fdiagnostics-hotness-threshold:
+
+**-fdiagnostics-hotness-threshold**
+ Prevent optimization remarks from being output if they do not have at least
+ this hotness value.
+
+ This option, which defaults to zero, controls the minimum hotness an
+ optimization remark would need in order to be output by Clang. This is
+ currently supported with optimization remarks (see :ref:`Options to Emit
+ Optimization Reports <rpass>`) when profile hotness information in
+ diagnostics is enabled (see
+ :ref:`-fdiagnostics-show-hotness <opt_fdiagnostics-show-hotness>`).
+
.. _opt_fdiagnostics-fixit-info:
**-f[no-]diagnostics-fixit-info**
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h
index 4241e43a9697..f404e6d72ec9 100644
--- a/include/clang-c/Index.h
+++ b/include/clang-c/Index.h
@@ -171,7 +171,60 @@ typedef struct CXVersion {
*/
int Subminor;
} CXVersion;
-
+
+/**
+ * \brief Describes the exception specification of a cursor.
+ *
+ * A negative value indicates that the cursor is not a function declaration.
+ */
+enum CXCursor_ExceptionSpecificationKind {
+
+ /**
+ * \brief The cursor has no exception specification.
+ */
+ CXCursor_ExceptionSpecificationKind_None,
+
+ /**
+ * \brief The cursor has exception specification throw()
+ */
+ CXCursor_ExceptionSpecificationKind_DynamicNone,
+
+ /**
+ * \brief The cursor has exception specification throw(T1, T2)
+ */
+ CXCursor_ExceptionSpecificationKind_Dynamic,
+
+ /**
+ * \brief The cursor has exception specification throw(...).
+ */
+ CXCursor_ExceptionSpecificationKind_MSAny,
+
+ /**
+ * \brief The cursor has exception specification basic noexcept.
+ */
+ CXCursor_ExceptionSpecificationKind_BasicNoexcept,
+
+ /**
+ * \brief The cursor has exception specification computed noexcept.
+ */
+ CXCursor_ExceptionSpecificationKind_ComputedNoexcept,
+
+ /**
+ * \brief The exception specification has not yet been evaluated.
+ */
+ CXCursor_ExceptionSpecificationKind_Unevaluated,
+
+ /**
+ * \brief The exception specification has not yet been instantiated.
+ */
+ CXCursor_ExceptionSpecificationKind_Uninstantiated,
+
+ /**
+ * \brief The exception specification has not been parsed yet.
+ */
+ CXCursor_ExceptionSpecificationKind_Unparsed
+};
+
/**
* \brief Provides a shared context for creating translation units.
*
@@ -3471,6 +3524,13 @@ CINDEX_LINKAGE enum CXCallingConv clang_getFunctionTypeCallingConv(CXType T);
CINDEX_LINKAGE CXType clang_getResultType(CXType T);
/**
+ * \brief Retrieve the exception specification type associated with a function type.
+ *
+ * If a non-function type is passed in, an error code of -1 is returned.
+ */
+CINDEX_LINKAGE int clang_getExceptionSpecificationType(CXType T);
+
+/**
* \brief Retrieve the number of non-variadic parameters associated with a
* function type.
*
@@ -3499,6 +3559,13 @@ CINDEX_LINKAGE unsigned clang_isFunctionTypeVariadic(CXType T);
CINDEX_LINKAGE CXType clang_getCursorResultType(CXCursor C);
/**
+ * \brief Retrieve the exception specification type associated with a given cursor.
+ *
+ * This only returns a valid result if the cursor refers to a function or method.
+ */
+CINDEX_LINKAGE int clang_getCursorExceptionSpecificationType(CXCursor C);
+
+/**
* \brief Return 1 if the CXType is a POD (plain old data) type, and 0
* otherwise.
*/
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index 4c379620ab2d..3b46d31458ce 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -2050,6 +2050,11 @@ public:
/// Get the offset of a FieldDecl or IndirectFieldDecl, in bits.
uint64_t getFieldOffset(const ValueDecl *FD) const;
+ /// Get the offset of an ObjCIvarDecl in bits.
+ uint64_t lookupFieldBitOffset(const ObjCInterfaceDecl *OID,
+ const ObjCImplementationDecl *ID,
+ const ObjCIvarDecl *Ivar) const;
+
bool isNearlyEmpty(const CXXRecordDecl *RD) const;
VTableContextBase *getVTableContext();
diff --git a/include/clang/AST/ASTStructuralEquivalence.h b/include/clang/AST/ASTStructuralEquivalence.h
index 770bb5763fbd..23674c65f332 100644
--- a/include/clang/AST/ASTStructuralEquivalence.h
+++ b/include/clang/AST/ASTStructuralEquivalence.h
@@ -62,9 +62,11 @@ struct StructuralEquivalenceContext {
StructuralEquivalenceContext(
ASTContext &FromCtx, ASTContext &ToCtx,
llvm::DenseSet<std::pair<Decl *, Decl *>> &NonEquivalentDecls,
- bool StrictTypeSpelling = false, bool Complain = true)
+ bool StrictTypeSpelling = false, bool Complain = true,
+ bool ErrorOnTagTypeMismatch = false)
: FromCtx(FromCtx), ToCtx(ToCtx), NonEquivalentDecls(NonEquivalentDecls),
- StrictTypeSpelling(StrictTypeSpelling), Complain(Complain),
+ StrictTypeSpelling(StrictTypeSpelling),
+ ErrorOnTagTypeMismatch(ErrorOnTagTypeMismatch), Complain(Complain),
LastDiagFromC2(false) {}
DiagnosticBuilder Diag1(SourceLocation Loc, unsigned DiagID);
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index 30552be9b381..08b34a75aa60 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -2019,7 +2019,10 @@ public:
/// These functions have special behavior under C++1y [expr.new]:
/// An implementation is allowed to omit a call to a replaceable global
/// allocation function. [...]
- bool isReplaceableGlobalAllocationFunction() const;
+ ///
+ /// If this function is an aligned allocation/deallocation function, return
+ /// true through IsAligned.
+ bool isReplaceableGlobalAllocationFunction(bool *IsAligned = nullptr) const;
/// Compute the language linkage.
LanguageLinkage getLanguageLinkage() const;
diff --git a/include/clang/AST/NSAPI.h b/include/clang/AST/NSAPI.h
index 583f9d9f1deb..3757116e7c70 100644
--- a/include/clang/AST/NSAPI.h
+++ b/include/clang/AST/NSAPI.h
@@ -49,7 +49,7 @@ public:
NSStr_initWithString,
NSStr_initWithUTF8String
};
- static const unsigned NumNSStringMethods = 5;
+ static const unsigned NumNSStringMethods = 6;
IdentifierInfo *getNSClassId(NSClassIdKindKind K) const;
@@ -112,7 +112,7 @@ public:
NSMutableDict_setObjectForKeyedSubscript,
NSMutableDict_setValueForKey
};
- static const unsigned NumNSDictionaryMethods = 14;
+ static const unsigned NumNSDictionaryMethods = 13;
/// \brief The Objective-C NSDictionary selectors.
Selector getNSDictionarySelector(NSDictionaryMethodKind MK) const;
diff --git a/include/clang/AST/OpenMPClause.h b/include/clang/AST/OpenMPClause.h
index f977e63e04f6..14e73819f53d 100644
--- a/include/clang/AST/OpenMPClause.h
+++ b/include/clang/AST/OpenMPClause.h
@@ -20,6 +20,7 @@
#include "clang/AST/Stmt.h"
#include "clang/Basic/OpenMPKinds.h"
#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/MapVector.h"
namespace clang {
@@ -3001,7 +3002,7 @@ protected:
// Organize the components by declaration and retrieve the original
// expression. Original expressions are always the first component of the
// mappable component list.
- llvm::DenseMap<ValueDecl *, SmallVector<MappableExprComponentListRef, 8>>
+ llvm::MapVector<ValueDecl *, SmallVector<MappableExprComponentListRef, 8>>
ComponentListMap;
{
auto CI = ComponentLists.begin();
diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h
index ad3f40d0d3f6..152e05bca740 100644
--- a/include/clang/AST/RecursiveASTVisitor.h
+++ b/include/clang/AST/RecursiveASTVisitor.h
@@ -593,6 +593,16 @@ bool RecursiveASTVisitor<Derived>::PostVisitStmt(Stmt *S) {
#define STMT(CLASS, PARENT) \
case Stmt::CLASS##Class: \
TRY_TO(WalkUpFrom##CLASS(static_cast<CLASS *>(S))); break;
+#define INITLISTEXPR(CLASS, PARENT) \
+ case Stmt::CLASS##Class: \
+ { \
+ auto ILE = static_cast<CLASS *>(S); \
+ if (auto Syn = ILE->isSemanticForm() ? ILE->getSyntacticForm() : ILE) \
+ TRY_TO(WalkUpFrom##CLASS(Syn)); \
+ if (auto Sem = ILE->isSemanticForm() ? ILE : ILE->getSemanticForm()) \
+ TRY_TO(WalkUpFrom##CLASS(Sem)); \
+ break; \
+ }
#include "clang/AST/StmtNodes.inc"
}
@@ -2220,13 +2230,15 @@ bool RecursiveASTVisitor<Derived>::TraverseSynOrSemInitListExpr(
// the syntactic and the semantic form.
//
// There is no guarantee about which form \p S takes when this method is called.
-DEF_TRAVERSE_STMT(InitListExpr, {
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseInitListExpr(
+ InitListExpr *S, DataRecursionQueue *Queue) {
TRY_TO(TraverseSynOrSemInitListExpr(
S->isSemanticForm() ? S->getSyntacticForm() : S, Queue));
TRY_TO(TraverseSynOrSemInitListExpr(
S->isSemanticForm() ? S : S->getSemanticForm(), Queue));
- ShouldVisitChildren = false;
-})
+ return true;
+}
// GenericSelectionExpr is a special case because the types and expressions
// are interleaved. We also need to watch out for null types (default
diff --git a/include/clang/AST/Redeclarable.h b/include/clang/AST/Redeclarable.h
index cd5f186a2086..89a9d3c4cc21 100644
--- a/include/clang/AST/Redeclarable.h
+++ b/include/clang/AST/Redeclarable.h
@@ -21,6 +21,60 @@
namespace clang {
class ASTContext;
+// Some notes on redeclarables:
+//
+// - Every redeclarable is on a circular linked list.
+//
+// - Every decl has a pointer to the first element of the chain _and_ a
+// DeclLink that may point to one of 3 possible states:
+// - the "previous" (temporal) element in the chain
+// - the "latest" (temporal) element in the chain
+// - the an "uninitialized-latest" value (when newly-constructed)
+//
+// - The first element is also often called the canonical element. Every
+// element has a pointer to it so that "getCanonical" can be fast.
+//
+// - Most links in the chain point to previous, except the link out of
+// the first; it points to latest.
+//
+// - Elements are called "first", "previous", "latest" or
+// "most-recent" when referring to temporal order: order of addition
+// to the chain.
+//
+// - To make matters confusing, the DeclLink type uses the term "next"
+// for its pointer-storage internally (thus functions like
+// NextIsPrevious). It's easiest to just ignore the implementation of
+// DeclLink when making sense of the redeclaration chain.
+//
+// - There's also a "definition" link for several types of
+// redeclarable, where only one definition should exist at any given
+// time (and the defn pointer is stored in the decl's "data" which
+// is copied to every element on the chain when it's changed).
+//
+// Here is some ASCII art:
+//
+// "first" "latest"
+// "canonical" "most recent"
+// +------------+ first +--------------+
+// | | <--------------------------- | |
+// | | | |
+// | | | |
+// | | +--------------+ | |
+// | | first | | | |
+// | | <---- | | | |
+// | | | | | |
+// | @class A | link | @interface A | link | @class A |
+// | seen first | <---- | seen second | <---- | seen third |
+// | | | | | |
+// +------------+ +--------------+ +--------------+
+// | data | defn | data | defn | data |
+// | | ----> | | <---- | |
+// +------------+ +--------------+ +--------------+
+// | | ^ ^
+// | |defn | |
+// | link +-----+ |
+// +-->-------------------------------------------+
+
/// \brief Provides common interface for the Decls that can be redeclared.
template<typename decl_type>
class Redeclarable {
diff --git a/include/clang/Basic/AttrDocs.td b/include/clang/Basic/AttrDocs.td
index 65dd7445ba26..2987f07d8bb4 100644
--- a/include/clang/Basic/AttrDocs.td
+++ b/include/clang/Basic/AttrDocs.td
@@ -605,20 +605,27 @@ semantics:
for ``T`` and ``U`` to be incompatible.
The declaration of ``overloadable`` functions is restricted to function
-declarations and definitions. Most importantly, if any function with a given
-name is given the ``overloadable`` attribute, then all function declarations
-and definitions with that name (and in that scope) must have the
-``overloadable`` attribute. This rule even applies to redeclarations of
-functions whose original declaration had the ``overloadable`` attribute, e.g.,
+declarations and definitions. If a function is marked with the ``overloadable``
+attribute, then all declarations and definitions of functions with that name,
+except for at most one (see the note below about unmarked overloads), must have
+the ``overloadable`` attribute. In addition, redeclarations of a function with
+the ``overloadable`` attribute must have the ``overloadable`` attribute, and
+redeclarations of a function without the ``overloadable`` attribute must *not*
+have the ``overloadable`` attribute. e.g.,
.. code-block:: c
int f(int) __attribute__((overloadable));
float f(float); // error: declaration of "f" must have the "overloadable" attribute
+ int f(int); // error: redeclaration of "f" must have the "overloadable" attribute
int g(int) __attribute__((overloadable));
int g(int) { } // error: redeclaration of "g" must also have the "overloadable" attribute
+ int h(int);
+ int h(int) __attribute__((overloadable)); // error: declaration of "h" must not
+ // have the "overloadable" attribute
+
Functions marked ``overloadable`` must have prototypes. Therefore, the
following code is ill-formed:
@@ -651,7 +658,28 @@ caveats to this use of name mangling:
linkage specification, it's name *will* be mangled in the same way as it
would in C.
-Query for this feature with ``__has_extension(attribute_overloadable)``.
+For the purpose of backwards compatibility, at most one function with the same
+name as other ``overloadable`` functions may omit the ``overloadable``
+attribute. In this case, the function without the ``overloadable`` attribute
+will not have its name mangled.
+
+For example:
+
+.. code-block:: c
+
+ // Notes with mangled names assume Itanium mangling.
+ int f(int);
+ int f(double) __attribute__((overloadable));
+ void foo() {
+ f(5); // Emits a call to f (not _Z1fi, as it would with an overload that
+ // was marked with overloadable).
+ f(1.0); // Emits a call to _Z1fd.
+ }
+
+Support for unmarked overloads is not present in some versions of clang. You may
+query for it using ``__has_extension(overloadable_unmarked)``.
+
+Query for this attribute with ``__has_attribute(overloadable)``.
}];
}
diff --git a/include/clang/Basic/BuiltinsNios2.def b/include/clang/Basic/BuiltinsNios2.def
new file mode 100644
index 000000000000..d9697e795c44
--- /dev/null
+++ b/include/clang/Basic/BuiltinsNios2.def
@@ -0,0 +1,70 @@
+//===-- BuiltinsNios2.def - Nios2 Builtin function database --------*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the Nios2-specific builtin function database. Users of
+// this file must define the BUILTIN macro to make use of this information.
+//
+//===----------------------------------------------------------------------===//
+
+// The format of this database matches clang/Basic/Builtins.def.
+
+#if defined(BUILTIN) && !defined(TARGET_BUILTIN)
+# define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) BUILTIN(ID, TYPE, ATTRS)
+#endif
+
+// Nios2 R1 builtins:
+
+//int __builtin_ldbio(volatile const void *);
+BUILTIN(__builtin_ldbio, "ivDC*", "")
+//int __builtin_ldbuio(volatile const void *);
+BUILTIN(__builtin_ldbuio, "ivDC*", "")
+//int __builtin_ldhio(volatile const void *);
+BUILTIN(__builtin_ldhio, "ivDC*", "")
+//int __builtin_ldhuio(volatile const void *);
+BUILTIN(__builtin_ldhuio, "ivDC*", "")
+//int __builtin_ldwio(volatile const void *);
+BUILTIN(__builtin_ldwio, "ivDC*", "")
+//int __builtin_ldwuio(int);
+BUILTIN(__builtin_ldwuio, "ii", "")
+// int __builtin_rdctl(int);
+BUILTIN(__builtin_rdctl, "iIi", "")
+// void __builtin_wrctl(int, int);
+BUILTIN(__builtin_wrctl, "vIii", "")
+// int __builtin_rdprs(int, int);
+BUILTIN(__builtin_rdprs, "iii", "")
+//void __builtin_stbio(volatile void *, int);
+BUILTIN(__builtin_stbio, "vvD*i", "")
+//void __builtin_sthio(volatile void *, int);
+BUILTIN(__builtin_sthio, "vvD*i", "")
+//void __builtin_stwio(volatile void *, int);
+BUILTIN(__builtin_stwio, "vvD*i", "")
+//void __builtin_sync(void);
+BUILTIN(__builtin_sync, "v", "")
+// void __builtin_flushd(volatile void *);
+BUILTIN(__builtin_flushd, "vvD*", "")
+// void __builtin_flushda(volatile void *);
+BUILTIN(__builtin_flushda, "vvD*", "")
+
+// Nios2 R2 builtins:
+
+// int __builtin_wrpie(int);
+TARGET_BUILTIN(__builtin_wrpie, "ii", "", "nios2r2mandatory")
+// void __builtin_eni(int);
+TARGET_BUILTIN(__builtin_eni, "vi", "", "nios2r2mandatory")
+// int __builtin_ldex(volatile const void *);
+TARGET_BUILTIN(__builtin_ldex, "ivDC*", "", "nios2r2mandatory")
+// int __builtin_stex(volatile void *, int);
+TARGET_BUILTIN(__builtin_stex, "ivD*i", "", "nios2r2mandatory")
+// int __builtin_ldsex(volatile const void *);
+TARGET_BUILTIN(__builtin_ldsex, "ivDC*", "", "nios2r2mpx")
+// int __builtin_stsex(volatile void *, int);
+TARGET_BUILTIN(__builtin_stsex, "ivDC*i", "", "nios2r2mpx")
+
+#undef BUILTIN
+#undef TARGET_BUILTIN
diff --git a/include/clang/Basic/BuiltinsWebAssembly.def b/include/clang/Basic/BuiltinsWebAssembly.def
index de56908be83c..19318dcebb9e 100644
--- a/include/clang/Basic/BuiltinsWebAssembly.def
+++ b/include/clang/Basic/BuiltinsWebAssembly.def
@@ -21,4 +21,8 @@
BUILTIN(__builtin_wasm_current_memory, "z", "n")
BUILTIN(__builtin_wasm_grow_memory, "zz", "n")
+// Exception handling builtins.
+BUILTIN(__builtin_wasm_throw, "vUiv*", "r")
+BUILTIN(__builtin_wasm_rethrow, "v", "r")
+
#undef BUILTIN
diff --git a/include/clang/Basic/DiagnosticASTKinds.td b/include/clang/Basic/DiagnosticASTKinds.td
index 652d06278557..b3cba2066edd 100644
--- a/include/clang/Basic/DiagnosticASTKinds.td
+++ b/include/clang/Basic/DiagnosticASTKinds.td
@@ -200,12 +200,17 @@ def note_odr_defined_here : Note<"also defined here">;
def err_odr_function_type_inconsistent : Error<
"external function %0 declared with incompatible types in different "
"translation units (%1 vs. %2)">;
-def warn_odr_tag_type_inconsistent : Warning<
- "type %0 has incompatible definitions in different translation units">,
- InGroup<DiagGroup<"odr">>;
+def warn_odr_tag_type_inconsistent
+ : Warning<"type %0 has incompatible definitions in different translation "
+ "units">,
+ InGroup<DiagGroup<"odr">>;
+def err_odr_tag_type_inconsistent
+ : Error<"type %0 has incompatible definitions in different translation "
+ "units">;
def note_odr_tag_kind_here: Note<
"%0 is a %select{struct|interface|union|class|enum}1 here">;
def note_odr_field : Note<"field %0 has type %1 here">;
+def note_odr_field_name : Note<"field has name %0 here">;
def note_odr_missing_field : Note<"no corresponding field here">;
def note_odr_bit_field : Note<"bit-field %0 with type %1 and length %2 here">;
def note_odr_not_bit_field : Note<"field %0 is not a bit-field">;
diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td
index eb6dd37c148d..42e1e5edaf9e 100644
--- a/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/include/clang/Basic/DiagnosticDriverKinds.td
@@ -138,6 +138,9 @@ def err_drv_cc_print_options_failure : Error<
def err_drv_lto_without_lld : Error<"LTO requires -fuse-ld=lld">;
def err_drv_preamble_format : Error<
"incorrect format for -preamble-bytes=N,END">;
+def err_invalid_ios_deployment_target : Error<
+ "invalid iOS deployment version '%0', iOS 10 is the maximum deployment "
+ "target for 32-bit targets">;
def err_drv_conflicting_deployment_targets : Error<
"conflicting deployment targets, both '%0' and '%1' are present in environment">;
def err_arc_unsupported_on_runtime : Error<
@@ -195,8 +198,8 @@ def warn_drv_unused_argument : Warning<
def warn_drv_empty_joined_argument : Warning<
"joined argument expects additional value: '%0'">,
InGroup<UnusedCommandLineArgument>;
-def warn_drv_fdiagnostics_show_hotness_requires_pgo : Warning<
- "argument '-fdiagnostics-show-hotness' requires profile-guided optimization information">,
+def warn_drv_diagnostics_hotness_requires_pgo : Warning<
+ "argument '%0' requires profile-guided optimization information">,
InGroup<UnusedCommandLineArgument>;
def warn_drv_clang_unsupported : Warning<
"the clang compiler does not support '%0'">;
diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td
index 464c2425a1f1..3a0564806b32 100644
--- a/include/clang/Basic/DiagnosticGroups.td
+++ b/include/clang/Basic/DiagnosticGroups.td
@@ -311,6 +311,7 @@ def : DiagGroup<"nonportable-cfstrings">;
def NonVirtualDtor : DiagGroup<"non-virtual-dtor">;
def : DiagGroup<"effc++", [NonVirtualDtor]>;
def OveralignedType : DiagGroup<"over-aligned">;
+def AlignedAllocationUnavailable : DiagGroup<"aligned-allocation-unavailable">;
def OldStyleCast : DiagGroup<"old-style-cast">;
def : DiagGroup<"old-style-definition">;
def OutOfLineDeclaration : DiagGroup<"out-of-line-declaration">;
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index cba9b251215a..136e48ab5e54 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3294,13 +3294,15 @@ def warn_iboutletcollection_property_assign : Warning<
"IBOutletCollection properties should be copy/strong and not assign">,
InGroup<ObjCInvalidIBOutletProperty>;
-def err_attribute_overloadable_missing : Error<
- "%select{overloaded function|redeclaration of}0 %1 must have the "
- "'overloadable' attribute">;
+def err_attribute_overloadable_mismatch : Error<
+ "redeclaration of %0 must %select{not |}1have the 'overloadable' attribute">;
def note_attribute_overloadable_prev_overload : Note<
- "previous overload of function is here">;
+ "previous %select{unmarked |}0overload of function is here">;
def err_attribute_overloadable_no_prototype : Error<
"'overloadable' function %0 must have a prototype">;
+def err_attribute_overloadable_multiple_unmarked_overloads : Error<
+ "at most one overload for a given name may lack the 'overloadable' "
+ "attribute">;
def warn_ns_attribute_wrong_return_type : Warning<
"%0 attribute only applies to %select{functions|methods|properties}1 that "
"return %select{an Objective-C object|a pointer|a non-retainable pointer}2">,
@@ -6405,6 +6407,12 @@ def warn_overaligned_type : Warning<
"type %0 requires %1 bytes of alignment and the default allocator only "
"guarantees %2 bytes">,
InGroup<OveralignedType>, DefaultIgnore;
+def warn_aligned_allocation_unavailable :Warning<
+ "aligned %select{allocation|deallocation}0 function of type '%1' possibly "
+ "unavailable on %2">, InGroup<AlignedAllocationUnavailable>, DefaultError;
+def note_silence_unligned_allocation_unavailable : Note<
+ "if you supply your own aligned allocation functions, use "
+ "-Wno-aligned-allocation-unavailable to silence this diagnostic">;
def err_conditional_void_nonvoid : Error<
"%select{left|right}1 operand to ? is void, but %select{right|left}1 operand "
@@ -8402,7 +8410,7 @@ def warn_opencl_attr_deprecated_ignored : Warning <
def err_opencl_variadic_function : Error<
"invalid prototype, variadic arguments are not allowed in OpenCL">;
def err_opencl_requires_extension : Error<
- "use of %select{type |declaration}0%1 requires %2 extension to be enabled">;
+ "use of %select{type|declaration}0 %1 requires %2 extension to be enabled">;
// OpenCL v2.0 s6.13.6 -- Builtin Pipe Functions
def err_opencl_builtin_pipe_first_arg : Error<
diff --git a/include/clang/Basic/LangOptions.def b/include/clang/Basic/LangOptions.def
index 60c8a68cd2e9..dfdad108922a 100644
--- a/include/clang/Basic/LangOptions.def
+++ b/include/clang/Basic/LangOptions.def
@@ -199,6 +199,7 @@ LANGOPT(CUDADeviceApproxTranscendentals, 1, 0, "using approximate transcendental
LANGOPT(SizedDeallocation , 1, 0, "sized deallocation")
LANGOPT(AlignedAllocation , 1, 0, "aligned allocation")
+LANGOPT(AlignedAllocationUnavailable, 1, 0, "aligned allocation functions are unavailable")
LANGOPT(NewAlignOverride , 32, 0, "maximum alignment guaranteed by '::operator new(size_t)'")
LANGOPT(ConceptsTS , 1, 0, "enable C++ Extensions for Concepts")
BENIGN_LANGOPT(ModulesCodegen , 1, 0, "Modules code generation")
diff --git a/include/clang/Basic/OpenMPKinds.def b/include/clang/Basic/OpenMPKinds.def
index 74ec26f19ac2..aae1c3a9b8c5 100644
--- a/include/clang/Basic/OpenMPKinds.def
+++ b/include/clang/Basic/OpenMPKinds.def
@@ -552,6 +552,7 @@ OPENMP_TASKLOOP_CLAUSE(priority)
OPENMP_TASKLOOP_CLAUSE(grainsize)
OPENMP_TASKLOOP_CLAUSE(nogroup)
OPENMP_TASKLOOP_CLAUSE(num_tasks)
+OPENMP_TASKLOOP_CLAUSE(reduction)
// Clauses allowed for OpenMP directive 'taskloop simd'.
OPENMP_TASKLOOP_SIMD_CLAUSE(if)
@@ -572,6 +573,7 @@ OPENMP_TASKLOOP_SIMD_CLAUSE(simdlen)
OPENMP_TASKLOOP_SIMD_CLAUSE(grainsize)
OPENMP_TASKLOOP_SIMD_CLAUSE(nogroup)
OPENMP_TASKLOOP_SIMD_CLAUSE(num_tasks)
+OPENMP_TASKLOOP_SIMD_CLAUSE(reduction)
// Clauses allowed for OpenMP directive 'critical'.
OPENMP_CRITICAL_CLAUSE(hint)
diff --git a/include/clang/Basic/SourceLocation.h b/include/clang/Basic/SourceLocation.h
index f0fe4c27062e..12aa0e4f5717 100644
--- a/include/clang/Basic/SourceLocation.h
+++ b/include/clang/Basic/SourceLocation.h
@@ -262,6 +262,65 @@ public:
bool isInvalid() const { return !isValid(); }
};
+/// \brief Represents an unpacked "presumed" location which can be presented
+/// to the user.
+///
+/// A 'presumed' location can be modified by \#line and GNU line marker
+/// directives and is always the expansion point of a normal location.
+///
+/// You can get a PresumedLoc from a SourceLocation with SourceManager.
+class PresumedLoc {
+ const char *Filename;
+ unsigned Line, Col;
+ SourceLocation IncludeLoc;
+
+public:
+ PresumedLoc() : Filename(nullptr) {}
+ PresumedLoc(const char *FN, unsigned Ln, unsigned Co, SourceLocation IL)
+ : Filename(FN), Line(Ln), Col(Co), IncludeLoc(IL) {}
+
+ /// \brief Return true if this object is invalid or uninitialized.
+ ///
+ /// This occurs when created with invalid source locations or when walking
+ /// off the top of a \#include stack.
+ bool isInvalid() const { return Filename == nullptr; }
+ bool isValid() const { return Filename != nullptr; }
+
+ /// \brief Return the presumed filename of this location.
+ ///
+ /// This can be affected by \#line etc.
+ const char *getFilename() const {
+ assert(isValid());
+ return Filename;
+ }
+
+ /// \brief Return the presumed line number of this location.
+ ///
+ /// This can be affected by \#line etc.
+ unsigned getLine() const {
+ assert(isValid());
+ return Line;
+ }
+
+ /// \brief Return the presumed column number of this location.
+ ///
+ /// This cannot be affected by \#line, but is packaged here for convenience.
+ unsigned getColumn() const {
+ assert(isValid());
+ return Col;
+ }
+
+ /// \brief Return the presumed include location of this location.
+ ///
+ /// This can be affected by GNU linemarker directives.
+ SourceLocation getIncludeLoc() const {
+ assert(isValid());
+ return IncludeLoc;
+ }
+};
+
+class FileEntry;
+
/// \brief A SourceLocation and its associated SourceManager.
///
/// This is useful for argument passing to functions that expect both objects.
@@ -274,6 +333,12 @@ public:
explicit FullSourceLoc(SourceLocation Loc, const SourceManager &SM)
: SourceLocation(Loc), SrcMgr(&SM) {}
+ bool hasManager() const {
+ bool hasSrcMgr = SrcMgr != nullptr;
+ assert(hasSrcMgr == isValid() && "FullSourceLoc has location but no manager");
+ return hasSrcMgr;
+ }
+
/// \pre This FullSourceLoc has an associated SourceManager.
const SourceManager &getManager() const {
assert(SrcMgr && "SourceManager is NULL.");
@@ -284,6 +349,13 @@ public:
FullSourceLoc getExpansionLoc() const;
FullSourceLoc getSpellingLoc() const;
+ FullSourceLoc getFileLoc() const;
+ std::pair<FullSourceLoc, FullSourceLoc> getImmediateExpansionRange() const;
+ PresumedLoc getPresumedLoc(bool UseLineDirectives = true) const;
+ bool isMacroArgExpansion(FullSourceLoc *StartLoc = nullptr) const;
+ FullSourceLoc getImmediateMacroCallerLoc() const;
+ std::pair<FullSourceLoc, StringRef> getModuleImportLoc() const;
+ unsigned getFileOffset() const;
unsigned getExpansionLineNumber(bool *Invalid = nullptr) const;
unsigned getExpansionColumnNumber(bool *Invalid = nullptr) const;
@@ -293,6 +365,12 @@ public:
const char *getCharacterData(bool *Invalid = nullptr) const;
+ unsigned getLineNumber(bool *Invalid = nullptr) const;
+ unsigned getColumnNumber(bool *Invalid = nullptr) const;
+
+ std::pair<FullSourceLoc, FullSourceLoc> getExpansionRange() const;
+
+ const FileEntry *getFileEntry() const;
/// \brief Return a StringRef to the source buffer data for the
/// specified FileID.
@@ -345,50 +423,6 @@ public:
};
-/// \brief Represents an unpacked "presumed" location which can be presented
-/// to the user.
-///
-/// A 'presumed' location can be modified by \#line and GNU line marker
-/// directives and is always the expansion point of a normal location.
-///
-/// You can get a PresumedLoc from a SourceLocation with SourceManager.
-class PresumedLoc {
- const char *Filename;
- unsigned Line, Col;
- SourceLocation IncludeLoc;
-public:
- PresumedLoc() : Filename(nullptr) {}
- PresumedLoc(const char *FN, unsigned Ln, unsigned Co, SourceLocation IL)
- : Filename(FN), Line(Ln), Col(Co), IncludeLoc(IL) {
- }
-
- /// \brief Return true if this object is invalid or uninitialized.
- ///
- /// This occurs when created with invalid source locations or when walking
- /// off the top of a \#include stack.
- bool isInvalid() const { return Filename == nullptr; }
- bool isValid() const { return Filename != nullptr; }
-
- /// \brief Return the presumed filename of this location.
- ///
- /// This can be affected by \#line etc.
- const char *getFilename() const { assert(isValid()); return Filename; }
-
- /// \brief Return the presumed line number of this location.
- ///
- /// This can be affected by \#line etc.
- unsigned getLine() const { assert(isValid()); return Line; }
-
- /// \brief Return the presumed column number of this location.
- ///
- /// This cannot be affected by \#line, but is packaged here for convenience.
- unsigned getColumn() const { assert(isValid()); return Col; }
-
- /// \brief Return the presumed include location of this location.
- ///
- /// This can be affected by GNU linemarker directives.
- SourceLocation getIncludeLoc() const { assert(isValid()); return IncludeLoc; }
-};
} // end namespace clang
diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h
index 5e01f6416748..ed3f8dfa86e7 100644
--- a/include/clang/Basic/SourceManager.h
+++ b/include/clang/Basic/SourceManager.h
@@ -80,9 +80,19 @@ namespace SrcMgr {
/// system_header is seen or in various other cases.
///
enum CharacteristicKind {
- C_User, C_System, C_ExternCSystem
+ C_User, C_System, C_ExternCSystem, C_User_ModuleMap, C_System_ModuleMap
};
+ /// Determine whether a file / directory characteristic is for system code.
+ inline bool isSystem(CharacteristicKind CK) {
+ return CK != C_User && CK != C_User_ModuleMap;
+ }
+
+ /// Determine whether a file characteristic is for a module map.
+ inline bool isModuleMap(CharacteristicKind CK) {
+ return CK == C_User_ModuleMap || CK == C_System_ModuleMap;
+ }
+
/// \brief One instance of this struct is kept for every file loaded or used.
///
/// This object owns the MemoryBuffer object.
@@ -251,12 +261,14 @@ namespace SrcMgr {
/// preprocessing of this \#include, including this SLocEntry.
///
/// Zero means the preprocessor didn't provide such info for this SLocEntry.
- unsigned NumCreatedFIDs;
+ unsigned NumCreatedFIDs : 31;
- /// \brief Contains the ContentCache* and the bits indicating the
- /// characteristic of the file and whether it has \#line info, all
- /// bitmangled together.
- uintptr_t Data;
+ /// \brief Whether this FileInfo has any \#line directives.
+ unsigned HasLineDirectives : 1;
+
+ /// \brief The content cache and the characteristic of the file.
+ llvm::PointerIntPair<const ContentCache*, 3, CharacteristicKind>
+ ContentAndKind;
friend class clang::SourceManager;
friend class clang::ASTWriter;
@@ -269,10 +281,9 @@ namespace SrcMgr {
FileInfo X;
X.IncludeLoc = IL.getRawEncoding();
X.NumCreatedFIDs = 0;
- X.Data = (uintptr_t)Con;
- assert((X.Data & 7) == 0 &&"ContentCache pointer insufficiently aligned");
- assert((unsigned)FileCharacter < 4 && "invalid file character");
- X.Data |= (unsigned)FileCharacter;
+ X.HasLineDirectives = false;
+ X.ContentAndKind.setPointer(Con);
+ X.ContentAndKind.setInt(FileCharacter);
return X;
}
@@ -280,22 +291,22 @@ namespace SrcMgr {
return SourceLocation::getFromRawEncoding(IncludeLoc);
}
- const ContentCache* getContentCache() const {
- return reinterpret_cast<const ContentCache*>(Data & ~uintptr_t(7));
+ const ContentCache *getContentCache() const {
+ return ContentAndKind.getPointer();
}
/// \brief Return whether this is a system header or not.
CharacteristicKind getFileCharacteristic() const {
- return (CharacteristicKind)(Data & 3);
+ return ContentAndKind.getInt();
}
/// \brief Return true if this FileID has \#line directives in it.
- bool hasLineDirectives() const { return (Data & 4) != 0; }
+ bool hasLineDirectives() const { return HasLineDirectives; }
/// \brief Set the flag that indicates that this FileID has
/// line table entries associated with it.
void setHasLineDirectives() {
- Data |= 4;
+ HasLineDirectives = true;
}
};
@@ -407,6 +418,8 @@ namespace SrcMgr {
};
public:
+ SLocEntry() : Offset(), IsExpansion(), File() {}
+
unsigned getOffset() const { return Offset; }
bool isExpansion() const { return IsExpansion; }
@@ -789,9 +802,8 @@ public:
FileID createFileID(const FileEntry *SourceFile, SourceLocation IncludePos,
SrcMgr::CharacteristicKind FileCharacter,
int LoadedID = 0, unsigned LoadedOffset = 0) {
- const SrcMgr::ContentCache *
- IR = getOrCreateContentCache(SourceFile,
- /*isSystemFile=*/FileCharacter != SrcMgr::C_User);
+ const SrcMgr::ContentCache *IR =
+ getOrCreateContentCache(SourceFile, isSystem(FileCharacter));
assert(IR && "getOrCreateContentCache() cannot return NULL");
return createFileID(IR, IncludePos, FileCharacter, LoadedID, LoadedOffset);
}
@@ -1360,7 +1372,7 @@ public:
/// \brief Returns if a SourceLocation is in a system header.
bool isInSystemHeader(SourceLocation Loc) const {
- return getFileCharacteristic(Loc) != SrcMgr::C_User;
+ return isSystem(getFileCharacteristic(Loc));
}
/// \brief Returns if a SourceLocation is in an "extern C" system header.
@@ -1477,6 +1489,17 @@ public:
/// \returns true if LHS source location comes before RHS, false otherwise.
bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const;
+ /// \brief Determines whether the two decomposed source location is in the
+ /// same translation unit. As a byproduct, it also calculates the order
+ /// of the source locations in case they are in the same TU.
+ ///
+ /// \returns Pair of bools the first component is true if the two locations
+ /// are in the same TU. The second bool is true if the first is true
+ /// and \p LOffs is before \p ROffs.
+ std::pair<bool, bool>
+ isInTheSameTranslationUnit(std::pair<FileID, unsigned> &LOffs,
+ std::pair<FileID, unsigned> &ROffs) const;
+
/// \brief Determines the order of 2 source locations in the "source location
/// address space".
bool isBeforeInSLocAddrSpace(SourceLocation LHS, SourceLocation RHS) const {
diff --git a/include/clang/Basic/TargetBuiltins.h b/include/clang/Basic/TargetBuiltins.h
index 5d45e162d9f6..8f4f5e9a74dd 100644
--- a/include/clang/Basic/TargetBuiltins.h
+++ b/include/clang/Basic/TargetBuiltins.h
@@ -150,6 +150,16 @@ namespace clang {
};
}
+ /// \brief Nios2 builtins
+ namespace Nios2 {
+ enum {
+ LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1,
+#define BUILTIN(ID, TYPE, ATTRS) BI##ID,
+#include "clang/Basic/BuiltinsNios2.def"
+ LastTSBuiltin
+ };
+ }
+
/// \brief MIPS builtins
namespace Mips {
enum {
diff --git a/include/clang/Basic/TargetOptions.h b/include/clang/Basic/TargetOptions.h
index 6ca1ba39c8fb..9bb19c7b79df 100644
--- a/include/clang/Basic/TargetOptions.h
+++ b/include/clang/Basic/TargetOptions.h
@@ -18,6 +18,7 @@
#include <string>
#include <vector>
#include "clang/Basic/OpenCLOptions.h"
+#include "llvm/Target/TargetOptions.h"
namespace clang {
@@ -41,7 +42,7 @@ public:
std::string ABI;
/// The EABI version to use
- std::string EABIVersion;
+ llvm::EABI EABIVersion;
/// If given, the version string of the linker in use.
std::string LinkerVersion;
diff --git a/include/clang/Basic/Visibility.h b/include/clang/Basic/Visibility.h
index 6ac52ed6b5e1..cc839d789e7f 100644
--- a/include/clang/Basic/Visibility.h
+++ b/include/clang/Basic/Visibility.h
@@ -75,6 +75,9 @@ public:
static LinkageInfo none() {
return LinkageInfo(NoLinkage, DefaultVisibility, false);
}
+ static LinkageInfo visible_none() {
+ return LinkageInfo(VisibleNoLinkage, DefaultVisibility, false);
+ }
Linkage getLinkage() const { return (Linkage)linkage_; }
Visibility getVisibility() const { return (Visibility)visibility_; }
diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td
index c478cfc7833e..205f36b723c8 100644
--- a/include/clang/Driver/CC1Options.td
+++ b/include/clang/Driver/CC1Options.td
@@ -145,7 +145,7 @@ def dwarf_debug_flags : Separate<["-"], "dwarf-debug-flags">,
HelpText<"The string to embed in the Dwarf debug flags record.">;
def compress_debug_sections : Flag<["-", "--"], "compress-debug-sections">,
HelpText<"DWARF debug sections compression">;
-def compress_debug_sections_EQ : Flag<["-"], "compress-debug-sections=">,
+def compress_debug_sections_EQ : Joined<["-"], "compress-debug-sections=">,
HelpText<"DWARF debug sections compression type">;
def mno_exec_stack : Flag<["-"], "mnoexecstack">,
HelpText<"Mark the file as not needing an executable stack">;
@@ -268,8 +268,6 @@ def vectorize_loops : Flag<["-"], "vectorize-loops">,
HelpText<"Run the Loop vectorization passes">;
def vectorize_slp : Flag<["-"], "vectorize-slp">,
HelpText<"Run the SLP vectorization passes">;
-def vectorize_slp_aggressive : Flag<["-"], "vectorize-slp-aggressive">,
- HelpText<"Run the BB vectorization passes">;
def dependent_lib : Joined<["--"], "dependent-lib=">,
HelpText<"Add dependent library">;
def linker_option : Joined<["--"], "linker-option=">,
@@ -323,6 +321,10 @@ def flto_unit: Flag<["-"], "flto-unit">,
def fno_lto_unit: Flag<["-"], "fno-lto-unit">;
def fthin_link_bitcode_EQ : Joined<["-"], "fthin-link-bitcode=">,
HelpText<"Write minimized bitcode to <file> for the ThinLTO thin link only">;
+def fdebug_pass_manager : Flag<["-"], "fdebug-pass-manager">,
+ HelpText<"Prints debug information for the new pass manager">;
+def fno_debug_pass_manager : Flag<["-"], "fno-debug-pass-manager">,
+ HelpText<"Disables debug printing for the new pass manager">;
//===----------------------------------------------------------------------===//
// Dependency Output Options
@@ -568,6 +570,9 @@ def find_pch_source_EQ : Joined<["-"], "find-pch-source=">,
def fno_pch_timestamp : Flag<["-"], "fno-pch-timestamp">,
HelpText<"Disable inclusion of timestamp in precompiled headers">;
+def aligned_alloc_unavailable : Flag<["-"], "faligned-alloc-unavailable">,
+ HelpText<"Aligned allocation/deallocation functions are unavailable">;
+
//===----------------------------------------------------------------------===//
// Language Options
//===----------------------------------------------------------------------===//
diff --git a/include/clang/Driver/Compilation.h b/include/clang/Driver/Compilation.h
index 114e0b33c75a..036b04605ac7 100644
--- a/include/clang/Driver/Compilation.h
+++ b/include/clang/Driver/Compilation.h
@@ -105,10 +105,13 @@ class Compilation {
/// Whether we're compiling for diagnostic purposes.
bool ForDiagnostics;
+ /// Whether an error during the parsing of the input args.
+ bool ContainsError;
+
public:
Compilation(const Driver &D, const ToolChain &DefaultToolChain,
llvm::opt::InputArgList *Args,
- llvm::opt::DerivedArgList *TranslatedArgs);
+ llvm::opt::DerivedArgList *TranslatedArgs, bool ContainsError);
~Compilation();
const Driver &getDriver() const { return TheDriver; }
@@ -275,6 +278,9 @@ public:
/// Return true if we're compiling for diagnostics.
bool isForDiagnostics() const { return ForDiagnostics; }
+ /// Return whether an error during the parsing of the input args.
+ bool containsError() const { return ContainsError; }
+
/// Redirect - Redirect output of this compilation. Can only be done once.
///
/// \param Redirects - array of pointers to paths. The array
diff --git a/include/clang/Driver/Driver.h b/include/clang/Driver/Driver.h
index 1009754a15d5..5a087eea1b4e 100644
--- a/include/clang/Driver/Driver.h
+++ b/include/clang/Driver/Driver.h
@@ -341,7 +341,8 @@ public:
/// ParseArgStrings - Parse the given list of strings into an
/// ArgList.
- llvm::opt::InputArgList ParseArgStrings(ArrayRef<const char *> Args);
+ llvm::opt::InputArgList ParseArgStrings(ArrayRef<const char *> Args,
+ bool &ContainsError);
/// BuildInputs - Construct the list of inputs and their types from
/// the given arguments.
diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td
index 68b331fed2bd..b65b984731f6 100644
--- a/include/clang/Driver/Options.td
+++ b/include/clang/Driver/Options.td
@@ -723,6 +723,9 @@ def fdiagnostics_print_source_range_info : Flag<["-"], "fdiagnostics-print-sourc
HelpText<"Print source range spans in numeric form">;
def fdiagnostics_show_hotness : Flag<["-"], "fdiagnostics-show-hotness">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Enable profile hotness information in diagnostic line">;
+def fdiagnostics_hotness_threshold_EQ : Joined<["-"], "fdiagnostics-hotness-threshold=">,
+ Group<f_Group>, Flags<[CC1Option]>, MetaVarName<"<number>">,
+ HelpText<"Prevent optimization remarks from being output if they do not have at least this profile count">;
def fdiagnostics_show_option : Flag<["-"], "fdiagnostics-show-option">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Print option name with mappable diagnostics">;
def fdiagnostics_show_note_include_stack : Flag<["-"], "fdiagnostics-show-note-include-stack">,
@@ -1405,9 +1408,6 @@ def : Flag<["-"], "fno-tree-vectorize">, Alias<fno_vectorize>;
def fslp_vectorize : Flag<["-"], "fslp-vectorize">, Group<f_Group>,
HelpText<"Enable the superword-level parallelism vectorization passes">;
def fno_slp_vectorize : Flag<["-"], "fno-slp-vectorize">, Group<f_Group>;
-def fslp_vectorize_aggressive : Flag<["-"], "fslp-vectorize-aggressive">, Group<f_Group>,
- HelpText<"Enable the BB vectorization passes">;
-def fno_slp_vectorize_aggressive : Flag<["-"], "fno-slp-vectorize-aggressive">, Group<f_Group>;
def : Flag<["-"], "ftree-slp-vectorize">, Alias<fslp_vectorize>;
def : Flag<["-"], "fno-tree-slp-vectorize">, Alias<fno_slp_vectorize>;
def Wlarge_by_value_copy_def : Flag<["-"], "Wlarge-by-value-copy">,
diff --git a/include/clang/Format/Format.h b/include/clang/Format/Format.h
index c1b62477ed1c..ee24c55fef61 100644
--- a/include/clang/Format/Format.h
+++ b/include/clang/Format/Format.h
@@ -717,7 +717,29 @@ struct FormatStyle {
/// }
/// \endcode
///
- bool SplitEmptyFunctionBody;
+ bool SplitEmptyFunction;
+ /// \brief If ``false``, empty record (e.g. class, struct or union) body
+ /// can be put on a single line. This option is used only if the opening
+ /// brace of the record has already been wrapped, i.e. the `AfterClass`
+ /// (for classes) brace wrapping mode is set.
+ /// \code
+ /// class Foo vs. class Foo
+ /// {} {
+ /// }
+ /// \endcode
+ ///
+ bool SplitEmptyRecord;
+ /// \brief If ``false``, empty namespace body can be put on a single line.
+ /// This option is used only if the opening brace of the namespace has
+ /// already been wrapped, i.e. the `AfterNamespace` brace wrapping mode is
+ /// set.
+ /// \code
+ /// namespace Foo vs. namespace Foo
+ /// {} {
+ /// }
+ /// \endcode
+ ///
+ bool SplitEmptyNamespace;
};
/// \brief Control of individual brace wrapping cases.
@@ -966,7 +988,7 @@ struct FormatStyle {
/// IncludeCategories:
/// - Regex: '^"(llvm|llvm-c|clang|clang-c)/'
/// Priority: 2
- /// - Regex: '^(<|"(gtest|isl|json)/)'
+ /// - Regex: '^(<|"(gtest|gmock|isl|json)/)'
/// Priority: 3
/// - Regex: '.*'
/// Priority: 1
diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h
index 2950c31c2d3d..1ac4f07a3549 100644
--- a/include/clang/Frontend/ASTUnit.h
+++ b/include/clang/Frontend/ASTUnit.h
@@ -628,6 +628,15 @@ public:
IntrusiveRefCntPtr<DiagnosticsEngine> Diags, bool CaptureDiagnostics,
bool UserFilesAreVolatile);
+ enum WhatToLoad {
+ /// Load options and the preprocessor state.
+ LoadPreprocessorOnly,
+ /// Load the AST, but do not restore Sema state.
+ LoadASTOnly,
+ /// Load everything, including Sema.
+ LoadEverything
+ };
+
/// \brief Create a ASTUnit from an AST file.
///
/// \param Filename - The AST file to load.
@@ -640,7 +649,7 @@ public:
/// \returns - The initialized ASTUnit or null if the AST failed to load.
static std::unique_ptr<ASTUnit> LoadFromASTFile(
const std::string &Filename, const PCHContainerReader &PCHContainerRdr,
- IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
+ WhatToLoad ToLoad, IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
const FileSystemOptions &FileSystemOpts, bool UseDebugInfo = false,
bool OnlyLocalDecls = false, ArrayRef<RemappedFile> RemappedFiles = None,
bool CaptureDiagnostics = false, bool AllowPCHWithCompilerErrors = false,
diff --git a/include/clang/Frontend/CodeGenOptions.def b/include/clang/Frontend/CodeGenOptions.def
index f3deb05ec6df..238bb231bdf5 100644
--- a/include/clang/Frontend/CodeGenOptions.def
+++ b/include/clang/Frontend/CodeGenOptions.def
@@ -57,6 +57,8 @@ CODEGENOPT(DisableLifetimeMarkers, 1, 0) ///< Don't emit any lifetime markers
CODEGENOPT(DisableO0ImplyOptNone , 1, 0) ///< Don't annonate function with optnone at O0
CODEGENOPT(ExperimentalNewPassManager, 1, 0) ///< Enables the new, experimental
///< pass manager.
+CODEGENOPT(DebugPassManager, 1, 0) ///< Prints debug information for the new
+ ///< pass manager.
CODEGENOPT(DisableRedZone , 1, 0) ///< Set when -mno-red-zone is enabled.
CODEGENOPT(DisableTailCalls , 1, 0) ///< Do not emit tail calls.
CODEGENOPT(EmitDeclMetadata , 1, 0) ///< Emit special metadata indicating what
@@ -177,7 +179,6 @@ CODEGENOPT(RerollLoops , 1, 0) ///< Control whether loops are rerolled.
CODEGENOPT(NoUseJumpTables , 1, 0) ///< Set when -fno-jump-tables is enabled.
CODEGENOPT(UnsafeFPMath , 1, 0) ///< Allow unsafe floating point optzns.
CODEGENOPT(UnwindTables , 1, 0) ///< Emit unwind tables.
-CODEGENOPT(VectorizeBB , 1, 0) ///< Run basic block vectorizer.
CODEGENOPT(VectorizeLoop , 1, 0) ///< Run loop vectorizer.
CODEGENOPT(VectorizeSLP , 1, 0) ///< Run SLP vectorizer.
@@ -260,6 +261,10 @@ VALUE_CODEGENOPT(EmitCheckPathComponentsToStrip, 32, 0)
/// Whether to report the hotness of the code region for optimization remarks.
CODEGENOPT(DiagnosticsWithHotness, 1, 0)
+/// The minimum hotness value a diagnostic needs in order to be included in
+/// optimization diagnostics.
+VALUE_CODEGENOPT(DiagnosticsHotnessThreshold, 32, 0)
+
/// Whether copy relocations support is available when building as PIE.
CODEGENOPT(PIECopyRelocations, 1, 0)
diff --git a/include/clang/Frontend/DiagnosticRenderer.h b/include/clang/Frontend/DiagnosticRenderer.h
index 2588feb2b87d..e453d7db624c 100644
--- a/include/clang/Frontend/DiagnosticRenderer.h
+++ b/include/clang/Frontend/DiagnosticRenderer.h
@@ -70,33 +70,27 @@ protected:
DiagnosticOptions *DiagOpts);
virtual ~DiagnosticRenderer();
-
- virtual void emitDiagnosticMessage(SourceLocation Loc, PresumedLoc PLoc,
+
+ virtual void emitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc,
DiagnosticsEngine::Level Level,
StringRef Message,
ArrayRef<CharSourceRange> Ranges,
- const SourceManager *SM,
DiagOrStoredDiag Info) = 0;
-
- virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
+
+ virtual void emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc,
DiagnosticsEngine::Level Level,
- ArrayRef<CharSourceRange> Ranges,
- const SourceManager &SM) = 0;
+ ArrayRef<CharSourceRange> Ranges) = 0;
- virtual void emitCodeContext(SourceLocation Loc,
+ virtual void emitCodeContext(FullSourceLoc Loc,
DiagnosticsEngine::Level Level,
- SmallVectorImpl<CharSourceRange>& Ranges,
- ArrayRef<FixItHint> Hints,
- const SourceManager &SM) = 0;
-
- virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc,
- const SourceManager &SM) = 0;
- virtual void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc,
- StringRef ModuleName,
- const SourceManager &SM) = 0;
- virtual void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc,
- StringRef ModuleName,
- const SourceManager &SM) = 0;
+ SmallVectorImpl<CharSourceRange> &Ranges,
+ ArrayRef<FixItHint> Hints) = 0;
+
+ virtual void emitIncludeLocation(FullSourceLoc Loc, PresumedLoc PLoc) = 0;
+ virtual void emitImportLocation(FullSourceLoc Loc, PresumedLoc PLoc,
+ StringRef ModuleName) = 0;
+ virtual void emitBuildingModuleLocation(FullSourceLoc Loc, PresumedLoc PLoc,
+ StringRef ModuleName) = 0;
virtual void beginDiagnostic(DiagOrStoredDiag D,
DiagnosticsEngine::Level Level) {}
@@ -106,25 +100,21 @@ protected:
private:
void emitBasicNote(StringRef Message);
- void emitIncludeStack(SourceLocation Loc, PresumedLoc PLoc,
- DiagnosticsEngine::Level Level, const SourceManager &SM);
- void emitIncludeStackRecursively(SourceLocation Loc, const SourceManager &SM);
- void emitImportStack(SourceLocation Loc, const SourceManager &SM);
- void emitImportStackRecursively(SourceLocation Loc, StringRef ModuleName,
- const SourceManager &SM);
+ void emitIncludeStack(FullSourceLoc Loc, PresumedLoc PLoc,
+ DiagnosticsEngine::Level Level);
+ void emitIncludeStackRecursively(FullSourceLoc Loc);
+ void emitImportStack(FullSourceLoc Loc);
+ void emitImportStackRecursively(FullSourceLoc Loc, StringRef ModuleName);
void emitModuleBuildStack(const SourceManager &SM);
- void emitCaret(SourceLocation Loc, DiagnosticsEngine::Level Level,
- ArrayRef<CharSourceRange> Ranges, ArrayRef<FixItHint> Hints,
- const SourceManager &SM);
- void emitSingleMacroExpansion(SourceLocation Loc,
+ void emitCaret(FullSourceLoc Loc, DiagnosticsEngine::Level Level,
+ ArrayRef<CharSourceRange> Ranges, ArrayRef<FixItHint> Hints);
+ void emitSingleMacroExpansion(FullSourceLoc Loc,
DiagnosticsEngine::Level Level,
- ArrayRef<CharSourceRange> Ranges,
- const SourceManager &SM);
- void emitMacroExpansions(SourceLocation Loc,
- DiagnosticsEngine::Level Level,
+ ArrayRef<CharSourceRange> Ranges);
+ void emitMacroExpansions(FullSourceLoc Loc, DiagnosticsEngine::Level Level,
ArrayRef<CharSourceRange> Ranges,
- ArrayRef<FixItHint> Hints,
- const SourceManager &SM);
+ ArrayRef<FixItHint> Hints);
+
public:
/// \brief Emit a diagnostic.
///
@@ -138,12 +128,9 @@ public:
/// \param Message The diagnostic message to emit.
/// \param Ranges The underlined ranges for this code snippet.
/// \param FixItHints The FixIt hints active for this diagnostic.
- /// \param SM The SourceManager; will be null if the diagnostic came from the
- /// frontend, thus \p Loc will be invalid.
- void emitDiagnostic(SourceLocation Loc, DiagnosticsEngine::Level Level,
+ void emitDiagnostic(FullSourceLoc Loc, DiagnosticsEngine::Level Level,
StringRef Message, ArrayRef<CharSourceRange> Ranges,
ArrayRef<FixItHint> FixItHints,
- const SourceManager *SM,
DiagOrStoredDiag D = (Diagnostic *)nullptr);
void emitStoredDiagnostic(StoredDiagnostic &Diag);
@@ -159,19 +146,15 @@ public:
~DiagnosticNoteRenderer() override;
- void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc,
- const SourceManager &SM) override;
+ void emitIncludeLocation(FullSourceLoc Loc, PresumedLoc PLoc) override;
- void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc,
- StringRef ModuleName,
- const SourceManager &SM) override;
+ void emitImportLocation(FullSourceLoc Loc, PresumedLoc PLoc,
+ StringRef ModuleName) override;
- void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc,
- StringRef ModuleName,
- const SourceManager &SM) override;
+ void emitBuildingModuleLocation(FullSourceLoc Loc, PresumedLoc PLoc,
+ StringRef ModuleName) override;
- virtual void emitNote(SourceLocation Loc, StringRef Message,
- const SourceManager *SM) = 0;
+ virtual void emitNote(FullSourceLoc Loc, StringRef Message) = 0;
};
} // end clang namespace
#endif
diff --git a/include/clang/Frontend/TextDiagnostic.h b/include/clang/Frontend/TextDiagnostic.h
index 9b108c28bd1c..1bbfe9fa02e3 100644
--- a/include/clang/Frontend/TextDiagnostic.h
+++ b/include/clang/Frontend/TextDiagnostic.h
@@ -75,44 +75,35 @@ public:
unsigned Columns, bool ShowColors);
protected:
- void emitDiagnosticMessage(SourceLocation Loc,PresumedLoc PLoc,
- DiagnosticsEngine::Level Level,
- StringRef Message,
+ void emitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc,
+ DiagnosticsEngine::Level Level, StringRef Message,
ArrayRef<CharSourceRange> Ranges,
- const SourceManager *SM,
DiagOrStoredDiag D) override;
- void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
+ void emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc,
DiagnosticsEngine::Level Level,
- ArrayRef<CharSourceRange> Ranges,
- const SourceManager &SM) override;
-
- void emitCodeContext(SourceLocation Loc,
- DiagnosticsEngine::Level Level,
- SmallVectorImpl<CharSourceRange>& Ranges,
- ArrayRef<FixItHint> Hints,
- const SourceManager &SM) override {
- emitSnippetAndCaret(Loc, Level, Ranges, Hints, SM);
+ ArrayRef<CharSourceRange> Ranges) override;
+
+ void emitCodeContext(FullSourceLoc Loc, DiagnosticsEngine::Level Level,
+ SmallVectorImpl<CharSourceRange> &Ranges,
+ ArrayRef<FixItHint> Hints) override {
+ emitSnippetAndCaret(Loc, Level, Ranges, Hints);
}
- void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc,
- const SourceManager &SM) override;
+ void emitIncludeLocation(FullSourceLoc Loc, PresumedLoc PLoc) override;
- void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc,
- StringRef ModuleName,
- const SourceManager &SM) override;
+ void emitImportLocation(FullSourceLoc Loc, PresumedLoc PLoc,
+ StringRef ModuleName) override;
- void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc,
- StringRef ModuleName,
- const SourceManager &SM) override;
+ void emitBuildingModuleLocation(FullSourceLoc Loc, PresumedLoc PLoc,
+ StringRef ModuleName) override;
private:
void emitFilename(StringRef Filename, const SourceManager &SM);
- void emitSnippetAndCaret(SourceLocation Loc, DiagnosticsEngine::Level Level,
- SmallVectorImpl<CharSourceRange>& Ranges,
- ArrayRef<FixItHint> Hints,
- const SourceManager &SM);
+ void emitSnippetAndCaret(FullSourceLoc Loc, DiagnosticsEngine::Level Level,
+ SmallVectorImpl<CharSourceRange> &Ranges,
+ ArrayRef<FixItHint> Hints);
void emitSnippet(StringRef SourceLine);
diff --git a/include/clang/Frontend/Utils.h b/include/clang/Frontend/Utils.h
index 0ee46846c804..8ccc31982dab 100644
--- a/include/clang/Frontend/Utils.h
+++ b/include/clang/Frontend/Utils.h
@@ -184,10 +184,11 @@ createChainedIncludesSource(CompilerInstance &CI,
///
/// \return A CompilerInvocation, or 0 if none was built for the given
/// argument vector.
-std::unique_ptr<CompilerInvocation>
-createInvocationFromCommandLine(ArrayRef<const char *> Args,
- IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
- IntrusiveRefCntPtr<DiagnosticsEngine>());
+std::unique_ptr<CompilerInvocation> createInvocationFromCommandLine(
+ ArrayRef<const char *> Args,
+ IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
+ IntrusiveRefCntPtr<DiagnosticsEngine>(),
+ IntrusiveRefCntPtr<vfs::FileSystem> VFS = nullptr);
/// Return the value of the last argument as an integer, or a default. If Diags
/// is non-null, emits an error if the argument is given, but non-integral.
diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h
index ee17dcbb8b5a..1b7f80c87ff1 100644
--- a/include/clang/Lex/HeaderSearch.h
+++ b/include/clang/Lex/HeaderSearch.h
@@ -47,7 +47,7 @@ struct HeaderFileInfo {
/// whether it is C++ clean or not. This can be set by the include paths or
/// by \#pragma gcc system_header. This is an instance of
/// SrcMgr::CharacteristicKind.
- unsigned DirInfo : 2;
+ unsigned DirInfo : 3;
/// \brief Whether this header file info was supplied by an external source,
/// and has not changed since.
diff --git a/include/clang/Lex/PTHLexer.h b/include/clang/Lex/PTHLexer.h
index 904be792b2a9..f96af665b157 100644
--- a/include/clang/Lex/PTHLexer.h
+++ b/include/clang/Lex/PTHLexer.h
@@ -36,7 +36,7 @@ class PTHLexer : public PreprocessorLexer {
const unsigned char* LastHashTokPtr;
/// PPCond - Pointer to a side table in the PTH file that provides a
- /// a consise summary of the preproccessor conditional block structure.
+ /// a concise summary of the preprocessor conditional block structure.
/// This is used to perform quick skipping of conditional blocks.
const unsigned char* PPCond;
diff --git a/include/clang/Sema/Lookup.h b/include/clang/Sema/Lookup.h
index 9134ddf9198c..ea32997d4066 100644
--- a/include/clang/Sema/Lookup.h
+++ b/include/clang/Sema/Lookup.h
@@ -18,6 +18,8 @@
#include "clang/AST/DeclCXX.h"
#include "clang/Sema/Sema.h"
+#include "llvm/ADT/Optional.h"
+
namespace clang {
/// @brief Represents the results of name lookup.
@@ -273,7 +275,7 @@ public:
/// declarations, such as those in modules that have not yet been imported.
bool isHiddenDeclarationVisible(NamedDecl *ND) const {
return AllowHidden ||
- (isForRedeclaration() && ND->isExternallyVisible());
+ (isForRedeclaration() && ND->hasExternalFormalLinkage());
}
/// Sets whether tag declarations should be hidden by non-tag
@@ -465,7 +467,7 @@ public:
Paths = nullptr;
}
} else {
- AmbiguityKind SavedAK;
+ llvm::Optional<AmbiguityKind> SavedAK;
bool WasAmbiguous = false;
if (ResultKind == Ambiguous) {
SavedAK = Ambiguity;
@@ -479,7 +481,7 @@ public:
if (ResultKind == Ambiguous) {
(void)WasAmbiguous;
assert(WasAmbiguous);
- Ambiguity = SavedAK;
+ Ambiguity = SavedAK.getValue();
} else if (Paths) {
deletePaths(Paths);
Paths = nullptr;
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 02c133d1c4fc..95134d52f873 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -1542,6 +1542,10 @@ public:
bool hasVisibleMergedDefinition(NamedDecl *Def);
+ /// Determine if \p D and \p Suggested have a structurally compatible
+ /// layout as described in C11 6.2.7/1.
+ bool hasStructuralCompatLayout(Decl *D, Decl *Suggested);
+
/// Determine if \p D has a visible definition. If not, suggest a declaration
/// that should be made visible to expose the definition.
bool hasVisibleDefinition(NamedDecl *D, NamedDecl **Suggested,
@@ -1629,9 +1633,13 @@ public:
//
struct SkipBodyInfo {
- SkipBodyInfo() : ShouldSkip(false), Previous(nullptr) {}
+ SkipBodyInfo()
+ : ShouldSkip(false), CheckSameAsPrevious(false), Previous(nullptr),
+ New(nullptr) {}
bool ShouldSkip;
+ bool CheckSameAsPrevious;
NamedDecl *Previous;
+ NamedDecl *New;
};
DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType = nullptr);
@@ -2145,13 +2153,11 @@ public:
};
Decl *ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
- SourceLocation KWLoc, CXXScopeSpec &SS,
- IdentifierInfo *Name, SourceLocation NameLoc,
- AttributeList *Attr, AccessSpecifier AS,
- SourceLocation ModulePrivateLoc,
- MultiTemplateParamsArg TemplateParameterLists,
- bool &OwnedDecl, bool &IsDependent,
- SourceLocation ScopedEnumKWLoc,
+ SourceLocation KWLoc, CXXScopeSpec &SS, IdentifierInfo *Name,
+ SourceLocation NameLoc, AttributeList *Attr,
+ AccessSpecifier AS, SourceLocation ModulePrivateLoc,
+ MultiTemplateParamsArg TemplateParameterLists, bool &OwnedDecl,
+ bool &IsDependent, SourceLocation ScopedEnumKWLoc,
bool ScopedEnumUsesClassTag, TypeResult UnderlyingType,
bool IsTypeSpecifier, bool IsTemplateParamOrArg,
SkipBodyInfo *SkipBody = nullptr);
@@ -2219,6 +2225,12 @@ public:
/// struct, or union).
void ActOnTagStartDefinition(Scope *S, Decl *TagDecl);
+ /// Perform ODR-like check for C/ObjC when merging tag types from modules.
+ /// Differently from C++, actually parse the body and reject / error out
+ /// in case of a structural mismatch.
+ bool ActOnDuplicateDefinition(DeclSpec &DS, Decl *Prev,
+ SkipBodyInfo &SkipBody);
+
typedef void *SkippedDefinitionContext;
/// \brief Invoked when we enter a tag definition that we're skipping.
@@ -2272,8 +2284,8 @@ public:
Decl *ActOnEnumConstant(Scope *S, Decl *EnumDecl, Decl *LastEnumConstant,
SourceLocation IdLoc, IdentifierInfo *Id,
- AttributeList *Attrs,
- SourceLocation EqualLoc, Expr *Val);
+ AttributeList *Attrs, SourceLocation EqualLoc,
+ Expr *Val);
void ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange,
Decl *EnumDecl,
ArrayRef<Decl *> Elements,
@@ -3233,7 +3245,7 @@ public:
void ProcessPragmaWeak(Scope *S, Decl *D);
// Decl attributes - this routine is the top level dispatcher.
void ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD);
- // Helper for delayed proccessing of attributes.
+ // Helper for delayed processing of attributes.
void ProcessDeclAttributeDelayed(Decl *D, const AttributeList *AttrList);
void ProcessDeclAttributeList(Scope *S, Decl *D, const AttributeList *AL,
bool IncludeCXX11Attributes = true);
@@ -8432,7 +8444,7 @@ public:
/// is disabled due to required OpenCL extensions being disabled. If so,
/// emit diagnostics.
/// \return true if type is disabled.
- bool checkOpenCLDisabledDecl(const Decl &D, const Expr &E);
+ bool checkOpenCLDisabledDecl(const NamedDecl &D, const Expr &E);
//===--------------------------------------------------------------------===//
// OpenMP directives and clauses.
@@ -10276,6 +10288,7 @@ private:
void CheckFloatComparison(SourceLocation Loc, Expr* LHS, Expr* RHS);
void CheckImplicitConversions(Expr *E, SourceLocation CC = SourceLocation());
void CheckBoolLikeConversion(Expr *E, SourceLocation CC);
+ void CheckForIntOverflow(Expr *E);
void CheckUnsequencedOperations(Expr *E);
/// \brief Perform semantic checks on a completed expression. This will either
diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h
index 737f6fb3d413..eafa05175832 100644
--- a/include/clang/Serialization/ASTReader.h
+++ b/include/clang/Serialization/ASTReader.h
@@ -400,7 +400,7 @@ private:
Preprocessor &PP;
/// \brief The AST context into which we'll read the AST files.
- ASTContext &Context;
+ ASTContext *ContextObj = nullptr;
/// \brief The AST consumer.
ASTConsumer *Consumer = nullptr;
@@ -1146,6 +1146,7 @@ private:
time_t StoredTime;
bool Overridden;
bool Transient;
+ bool TopLevelModuleMap;
};
/// \brief Reads the stored information about an input file.
@@ -1386,7 +1387,7 @@ public:
/// precompiled header will be loaded.
///
/// \param Context the AST context that this precompiled header will be
- /// loaded into.
+ /// loaded into, if any.
///
/// \param PCHContainerRdr the PCHContainerOperations to use for loading and
/// creating modules.
@@ -1418,7 +1419,7 @@ public:
///
/// \param ReadTimer If non-null, a timer used to track the time spent
/// deserializing.
- ASTReader(Preprocessor &PP, ASTContext &Context,
+ ASTReader(Preprocessor &PP, ASTContext *Context,
const PCHContainerReader &PCHContainerRdr,
ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
StringRef isysroot = "", bool DisableValidation = false,
@@ -2207,7 +2208,10 @@ public:
void completeVisibleDeclsMap(const DeclContext *DC) override;
/// \brief Retrieve the AST context that this AST reader supplements.
- ASTContext &getContext() { return Context; }
+ ASTContext &getContext() {
+ assert(ContextObj && "requested AST context when not loading AST");
+ return *ContextObj;
+ }
// \brief Contains the IDs for declarations that were requested before we have
// access to a Sema object.
@@ -2249,6 +2253,12 @@ public:
llvm::function_ref<void(const serialization::InputFile &IF,
bool isSystem)> Visitor);
+ /// Visit all the top-level module maps loaded when building the given module
+ /// file.
+ void visitTopLevelModuleMaps(serialization::ModuleFile &MF,
+ llvm::function_ref<
+ void(const FileEntry *)> Visitor);
+
bool isProcessingUpdateRecords() { return ProcessingUpdateRecords; }
};
diff --git a/include/clang/StaticAnalyzer/Checkers/Checkers.td b/include/clang/StaticAnalyzer/Checkers/Checkers.td
index 4171c685cb98..82ab720af8dc 100644
--- a/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -38,6 +38,11 @@ def CoreAlpha : Package<"core">, InPackage<Alpha>, Hidden;
// default. Such checkers belong in the alpha package.
def OptIn : Package<"optin">;
+// In the Portability package reside checkers for finding code that relies on
+// implementation-defined behavior. Such checks are wanted for cross-platform
+// development, but unwanted for developers who target only a single platform.
+def PortabilityOptIn : Package<"portability">, InPackage<OptIn>;
+
def Nullability : Package<"nullability">;
def Cplusplus : Package<"cplusplus">;
@@ -416,7 +421,7 @@ def GenericTaintChecker : Checker<"TaintPropagation">,
let ParentPackage = Unix in {
-def UnixAPIChecker : Checker<"API">,
+def UnixAPIMisuseChecker : Checker<"API">,
HelpText<"Check calls to various UNIX/Posix functions">,
DescFile<"UnixAPIChecker.cpp">;
@@ -754,3 +759,14 @@ def CloneChecker : Checker<"CloneChecker">,
} // end "clone"
+//===----------------------------------------------------------------------===//
+// Portability checkers.
+//===----------------------------------------------------------------------===//
+
+let ParentPackage = PortabilityOptIn in {
+
+def UnixAPIPortabilityChecker : Checker<"UnixAPI">,
+ HelpText<"Finds implementation-defined behavior in UNIX/Posix functions">,
+ DescFile<"UnixAPIChecker.cpp">;
+
+} // end optin.portability
diff --git a/include/clang/Tooling/Refactoring/Rename/RenamingAction.h b/include/clang/Tooling/Refactoring/Rename/RenamingAction.h
new file mode 100644
index 000000000000..099eaca6c42a
--- /dev/null
+++ b/include/clang/Tooling/Refactoring/Rename/RenamingAction.h
@@ -0,0 +1,70 @@
+//===--- RenamingAction.h - Clang refactoring library ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Provides an action to rename every symbol at a point.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_REFACTOR_RENAME_RENAMING_ACTION_H
+#define LLVM_CLANG_TOOLING_REFACTOR_RENAME_RENAMING_ACTION_H
+
+#include "clang/Tooling/Refactoring.h"
+
+namespace clang {
+class ASTConsumer;
+class CompilerInstance;
+
+namespace tooling {
+
+class RenamingAction {
+public:
+ RenamingAction(const std::vector<std::string> &NewNames,
+ const std::vector<std::string> &PrevNames,
+ const std::vector<std::vector<std::string>> &USRList,
+ std::map<std::string, tooling::Replacements> &FileToReplaces,
+ bool PrintLocations = false)
+ : NewNames(NewNames), PrevNames(PrevNames), USRList(USRList),
+ FileToReplaces(FileToReplaces), PrintLocations(PrintLocations) {}
+
+ std::unique_ptr<ASTConsumer> newASTConsumer();
+
+private:
+ const std::vector<std::string> &NewNames, &PrevNames;
+ const std::vector<std::vector<std::string>> &USRList;
+ std::map<std::string, tooling::Replacements> &FileToReplaces;
+ bool PrintLocations;
+};
+
+/// Rename all symbols identified by the given USRs.
+class QualifiedRenamingAction {
+public:
+ QualifiedRenamingAction(
+ const std::vector<std::string> &NewNames,
+ const std::vector<std::vector<std::string>> &USRList,
+ std::map<std::string, tooling::Replacements> &FileToReplaces)
+ : NewNames(NewNames), USRList(USRList), FileToReplaces(FileToReplaces) {}
+
+ std::unique_ptr<ASTConsumer> newASTConsumer();
+
+private:
+ /// New symbol names.
+ const std::vector<std::string> &NewNames;
+
+ /// A list of USRs. Each element represents USRs of a symbol being renamed.
+ const std::vector<std::vector<std::string>> &USRList;
+
+ /// A file path to replacements map.
+ std::map<std::string, tooling::Replacements> &FileToReplaces;
+};
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_REFACTOR_RENAME_RENAMING_ACTION_H
diff --git a/include/clang/Tooling/Refactoring/Rename/USRFinder.h b/include/clang/Tooling/Refactoring/Rename/USRFinder.h
new file mode 100644
index 000000000000..28d541af43c0
--- /dev/null
+++ b/include/clang/Tooling/Refactoring/Rename/USRFinder.h
@@ -0,0 +1,84 @@
+//===--- USRFinder.h - Clang refactoring library --------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Methods for determining the USR of a symbol at a location in source
+/// code.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_REFACTOR_RENAME_USR_FINDER_H
+#define LLVM_CLANG_TOOLING_REFACTOR_RENAME_USR_FINDER_H
+
+#include "clang/AST/AST.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include <string>
+#include <vector>
+
+using namespace llvm;
+using namespace clang::ast_matchers;
+
+namespace clang {
+
+class ASTContext;
+class Decl;
+class SourceLocation;
+class NamedDecl;
+
+namespace tooling {
+
+// Given an AST context and a point, returns a NamedDecl identifying the symbol
+// at the point. Returns null if nothing is found at the point.
+const NamedDecl *getNamedDeclAt(const ASTContext &Context,
+ const SourceLocation Point);
+
+// Given an AST context and a fully qualified name, returns a NamedDecl
+// identifying the symbol with a matching name. Returns null if nothing is
+// found for the name.
+const NamedDecl *getNamedDeclFor(const ASTContext &Context,
+ const std::string &Name);
+
+// Converts a Decl into a USR.
+std::string getUSRForDecl(const Decl *Decl);
+
+// FIXME: Implement RecursiveASTVisitor<T>::VisitNestedNameSpecifier instead.
+class NestedNameSpecifierLocFinder : public MatchFinder::MatchCallback {
+public:
+ explicit NestedNameSpecifierLocFinder(ASTContext &Context)
+ : Context(Context) {}
+
+ std::vector<NestedNameSpecifierLoc> getNestedNameSpecifierLocations() {
+ addMatchers();
+ Finder.matchAST(Context);
+ return Locations;
+ }
+
+private:
+ void addMatchers() {
+ const auto NestedNameSpecifierLocMatcher =
+ nestedNameSpecifierLoc().bind("nestedNameSpecifierLoc");
+ Finder.addMatcher(NestedNameSpecifierLocMatcher, this);
+ }
+
+ void run(const MatchFinder::MatchResult &Result) override {
+ const auto *NNS = Result.Nodes.getNodeAs<NestedNameSpecifierLoc>(
+ "nestedNameSpecifierLoc");
+ Locations.push_back(*NNS);
+ }
+
+ ASTContext &Context;
+ std::vector<NestedNameSpecifierLoc> Locations;
+ MatchFinder Finder;
+};
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_REFACTOR_RENAME_USR_FINDER_H
diff --git a/include/clang/Tooling/Refactoring/Rename/USRFindingAction.h b/include/clang/Tooling/Refactoring/Rename/USRFindingAction.h
new file mode 100644
index 000000000000..8aafee95bc09
--- /dev/null
+++ b/include/clang/Tooling/Refactoring/Rename/USRFindingAction.h
@@ -0,0 +1,54 @@
+//===--- USRFindingAction.h - Clang refactoring library -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Provides an action to find all relevant USRs at a point.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_REFACTOR_RENAME_USR_FINDING_ACTION_H
+#define LLVM_CLANG_TOOLING_REFACTOR_RENAME_USR_FINDING_ACTION_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
+
+#include <string>
+#include <vector>
+
+namespace clang {
+class ASTConsumer;
+class CompilerInstance;
+class NamedDecl;
+
+namespace tooling {
+
+struct USRFindingAction {
+ USRFindingAction(ArrayRef<unsigned> SymbolOffsets,
+ ArrayRef<std::string> QualifiedNames, bool Force)
+ : SymbolOffsets(SymbolOffsets), QualifiedNames(QualifiedNames),
+ ErrorOccurred(false), Force(Force) {}
+ std::unique_ptr<ASTConsumer> newASTConsumer();
+
+ ArrayRef<std::string> getUSRSpellings() { return SpellingNames; }
+ ArrayRef<std::vector<std::string>> getUSRList() { return USRList; }
+ bool errorOccurred() { return ErrorOccurred; }
+
+private:
+ std::vector<unsigned> SymbolOffsets;
+ std::vector<std::string> QualifiedNames;
+ std::vector<std::string> SpellingNames;
+ std::vector<std::vector<std::string>> USRList;
+ bool ErrorOccurred;
+ bool Force;
+};
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_REFACTOR_RENAME_USR_FINDING_ACTION_H
diff --git a/include/clang/Tooling/Refactoring/Rename/USRLocFinder.h b/include/clang/Tooling/Refactoring/Rename/USRLocFinder.h
new file mode 100644
index 000000000000..733ea1a6ac9e
--- /dev/null
+++ b/include/clang/Tooling/Refactoring/Rename/USRLocFinder.h
@@ -0,0 +1,49 @@
+//===--- USRLocFinder.h - Clang refactoring library -----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Provides functionality for finding all instances of a USR in a given
+/// AST.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_REFACTOR_RENAME_USR_LOC_FINDER_H
+#define LLVM_CLANG_TOOLING_REFACTOR_RENAME_USR_LOC_FINDER_H
+
+#include "clang/AST/AST.h"
+#include "clang/Tooling/Core/Replacement.h"
+#include "clang/Tooling/Refactoring/AtomicChange.h"
+#include "llvm/ADT/StringRef.h"
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace tooling {
+
+/// Create atomic changes for renaming all symbol references which are
+/// identified by the USRs set to a given new name.
+///
+/// \param USRs The set containing USRs of a particular old symbol.
+/// \param NewName The new name to replace old symbol name.
+/// \param TranslationUnitDecl The translation unit declaration.
+///
+/// \return Atomic changes for renaming.
+std::vector<tooling::AtomicChange>
+createRenameAtomicChanges(llvm::ArrayRef<std::string> USRs,
+ llvm::StringRef NewName, Decl *TranslationUnitDecl);
+
+// FIXME: make this an AST matcher. Wouldn't that be awesome??? I agree!
+std::vector<SourceLocation>
+getLocationsOfUSRs(const std::vector<std::string> &USRs,
+ llvm::StringRef PrevName, Decl *Decl);
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_REFACTOR_RENAME_USR_LOC_FINDER_H
diff --git a/include/clang/module.modulemap b/include/clang/module.modulemap
index 3b4238110026..f7e338d93399 100644
--- a/include/clang/module.modulemap
+++ b/include/clang/module.modulemap
@@ -33,6 +33,7 @@ module Clang_Basic {
textual header "Basic/BuiltinsLe64.def"
textual header "Basic/BuiltinsMips.def"
textual header "Basic/BuiltinsNEON.def"
+ textual header "Basic/BuiltinsNios2.def"
textual header "Basic/BuiltinsNVPTX.def"
textual header "Basic/BuiltinsPPC.def"
textual header "Basic/BuiltinsSystemZ.def"
@@ -132,9 +133,10 @@ module Clang_StaticAnalyzer_Frontend {
module Clang_Tooling {
requires cplusplus umbrella "Tooling" module * { export * }
- // FIXME: Exclude this header to avoid pulling all of the AST matchers
+ // FIXME: Exclude these headers to avoid pulling all of the AST matchers
// library into clang-format. Due to inline key functions in the headers,
// importing the AST matchers library gives a link dependency on the AST
// matchers (and thus the AST), which clang-format should not have.
exclude header "Tooling/RefactoringCallbacks.h"
+ exclude header "Tooling/Refactoring/Rename/USRFinder.h"
}
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index fabfdc9ef7e5..a2ff176df11f 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -5990,9 +5990,19 @@ static void EncodeBitField(const ASTContext *Ctx, std::string& S,
// compatibility with GCC, although providing it breaks anything that
// actually uses runtime introspection and wants to work on both runtimes...
if (Ctx->getLangOpts().ObjCRuntime.isGNUFamily()) {
- const RecordDecl *RD = FD->getParent();
- const ASTRecordLayout &RL = Ctx->getASTRecordLayout(RD);
- S += llvm::utostr(RL.getFieldOffset(FD->getFieldIndex()));
+ uint64_t Offset;
+
+ if (const auto *IVD = dyn_cast<ObjCIvarDecl>(FD)) {
+ Offset = Ctx->lookupFieldBitOffset(IVD->getContainingInterface(), nullptr,
+ IVD);
+ } else {
+ const RecordDecl *RD = FD->getParent();
+ const ASTRecordLayout &RL = Ctx->getASTRecordLayout(RD);
+ Offset = RL.getFieldOffset(FD->getFieldIndex());
+ }
+
+ S += llvm::utostr(Offset);
+
if (const EnumType *ET = T->getAs<EnumType>())
S += ObjCEncodingForEnumType(Ctx, ET);
else {
diff --git a/lib/AST/ASTStructuralEquivalence.cpp b/lib/AST/ASTStructuralEquivalence.cpp
index eff1aa5e323d..ea7faab767ed 100644
--- a/lib/AST/ASTStructuralEquivalence.cpp
+++ b/lib/AST/ASTStructuralEquivalence.cpp
@@ -735,13 +735,28 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
// Check for equivalent field names.
IdentifierInfo *Name1 = Field1->getIdentifier();
IdentifierInfo *Name2 = Field2->getIdentifier();
- if (!::IsStructurallyEquivalent(Name1, Name2))
+ if (!::IsStructurallyEquivalent(Name1, Name2)) {
+ if (Context.Complain) {
+ Context.Diag2(Owner2->getLocation(),
+ Context.ErrorOnTagTypeMismatch
+ ? diag::err_odr_tag_type_inconsistent
+ : diag::warn_odr_tag_type_inconsistent)
+ << Context.ToCtx.getTypeDeclType(Owner2);
+ Context.Diag2(Field2->getLocation(), diag::note_odr_field_name)
+ << Field2->getDeclName();
+ Context.Diag1(Field1->getLocation(), diag::note_odr_field_name)
+ << Field1->getDeclName();
+ }
return false;
+ }
if (!IsStructurallyEquivalent(Context, Field1->getType(),
Field2->getType())) {
if (Context.Complain) {
- Context.Diag2(Owner2->getLocation(), diag::warn_odr_tag_type_inconsistent)
+ Context.Diag2(Owner2->getLocation(),
+ Context.ErrorOnTagTypeMismatch
+ ? diag::err_odr_tag_type_inconsistent
+ : diag::warn_odr_tag_type_inconsistent)
<< Context.ToCtx.getTypeDeclType(Owner2);
Context.Diag2(Field2->getLocation(), diag::note_odr_field)
<< Field2->getDeclName() << Field2->getType();
@@ -753,7 +768,10 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
if (Field1->isBitField() != Field2->isBitField()) {
if (Context.Complain) {
- Context.Diag2(Owner2->getLocation(), diag::warn_odr_tag_type_inconsistent)
+ Context.Diag2(Owner2->getLocation(),
+ Context.ErrorOnTagTypeMismatch
+ ? diag::err_odr_tag_type_inconsistent
+ : diag::warn_odr_tag_type_inconsistent)
<< Context.ToCtx.getTypeDeclType(Owner2);
if (Field1->isBitField()) {
Context.Diag1(Field1->getLocation(), diag::note_odr_bit_field)
@@ -780,7 +798,9 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
if (Bits1 != Bits2) {
if (Context.Complain) {
Context.Diag2(Owner2->getLocation(),
- diag::warn_odr_tag_type_inconsistent)
+ Context.ErrorOnTagTypeMismatch
+ ? diag::err_odr_tag_type_inconsistent
+ : diag::warn_odr_tag_type_inconsistent)
<< Context.ToCtx.getTypeDeclType(Owner2);
Context.Diag2(Field2->getLocation(), diag::note_odr_bit_field)
<< Field2->getDeclName() << Field2->getType() << Bits2;
@@ -799,7 +819,10 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
RecordDecl *D1, RecordDecl *D2) {
if (D1->isUnion() != D2->isUnion()) {
if (Context.Complain) {
- Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
+ Context.Diag2(D2->getLocation(),
+ Context.ErrorOnTagTypeMismatch
+ ? diag::err_odr_tag_type_inconsistent
+ : diag::warn_odr_tag_type_inconsistent)
<< Context.ToCtx.getTypeDeclType(D2);
Context.Diag1(D1->getLocation(), diag::note_odr_tag_kind_here)
<< D1->getDeclName() << (unsigned)D1->getTagKind();
@@ -927,7 +950,10 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
Field1 != Field1End; ++Field1, ++Field2) {
if (Field2 == Field2End) {
if (Context.Complain) {
- Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
+ Context.Diag2(D2->getLocation(),
+ Context.ErrorOnTagTypeMismatch
+ ? diag::err_odr_tag_type_inconsistent
+ : diag::warn_odr_tag_type_inconsistent)
<< Context.ToCtx.getTypeDeclType(D2);
Context.Diag1(Field1->getLocation(), diag::note_odr_field)
<< Field1->getDeclName() << Field1->getType();
@@ -942,7 +968,10 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
if (Field2 != Field2End) {
if (Context.Complain) {
- Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
+ Context.Diag2(D2->getLocation(),
+ Context.ErrorOnTagTypeMismatch
+ ? diag::err_odr_tag_type_inconsistent
+ : diag::warn_odr_tag_type_inconsistent)
<< Context.ToCtx.getTypeDeclType(D2);
Context.Diag2(Field2->getLocation(), diag::note_odr_field)
<< Field2->getDeclName() << Field2->getType();
@@ -964,7 +993,10 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
EC1 != EC1End; ++EC1, ++EC2) {
if (EC2 == EC2End) {
if (Context.Complain) {
- Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
+ Context.Diag2(D2->getLocation(),
+ Context.ErrorOnTagTypeMismatch
+ ? diag::err_odr_tag_type_inconsistent
+ : diag::warn_odr_tag_type_inconsistent)
<< Context.ToCtx.getTypeDeclType(D2);
Context.Diag1(EC1->getLocation(), diag::note_odr_enumerator)
<< EC1->getDeclName() << EC1->getInitVal().toString(10);
@@ -978,7 +1010,10 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
if (!llvm::APSInt::isSameValue(Val1, Val2) ||
!IsStructurallyEquivalent(EC1->getIdentifier(), EC2->getIdentifier())) {
if (Context.Complain) {
- Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
+ Context.Diag2(D2->getLocation(),
+ Context.ErrorOnTagTypeMismatch
+ ? diag::err_odr_tag_type_inconsistent
+ : diag::warn_odr_tag_type_inconsistent)
<< Context.ToCtx.getTypeDeclType(D2);
Context.Diag2(EC2->getLocation(), diag::note_odr_enumerator)
<< EC2->getDeclName() << EC2->getInitVal().toString(10);
@@ -991,7 +1026,10 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
if (EC2 != EC2End) {
if (Context.Complain) {
- Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
+ Context.Diag2(D2->getLocation(),
+ Context.ErrorOnTagTypeMismatch
+ ? diag::err_odr_tag_type_inconsistent
+ : diag::warn_odr_tag_type_inconsistent)
<< Context.ToCtx.getTypeDeclType(D2);
Context.Diag2(EC2->getLocation(), diag::note_odr_enumerator)
<< EC2->getDeclName() << EC2->getInitVal().toString(10);
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 9862f4f26473..267c6992af89 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -1251,7 +1251,9 @@ static LinkageInfo computeLVForDecl(const NamedDecl *D,
case Decl::EnumConstant:
// C++ [basic.link]p4: an enumerator has the linkage of its enumeration.
- return getLVForDecl(cast<EnumDecl>(D->getDeclContext()), computation);
+ if (D->getASTContext().getLangOpts().CPlusPlus)
+ return getLVForDecl(cast<EnumDecl>(D->getDeclContext()), computation);
+ return LinkageInfo::visible_none();
case Decl::Typedef:
case Decl::TypeAlias:
@@ -2630,7 +2632,7 @@ bool FunctionDecl::isReservedGlobalPlacementOperator() const {
return (proto->getParamType(1).getCanonicalType() == Context.VoidPtrTy);
}
-bool FunctionDecl::isReplaceableGlobalAllocationFunction() const {
+bool FunctionDecl::isReplaceableGlobalAllocationFunction(bool *IsAligned) const {
if (getDeclName().getNameKind() != DeclarationName::CXXOperatorName)
return false;
if (getDeclName().getCXXOverloadedOperator() != OO_New &&
@@ -2676,8 +2678,11 @@ bool FunctionDecl::isReplaceableGlobalAllocationFunction() const {
// In C++17, the next parameter can be a 'std::align_val_t' for aligned
// new/delete.
- if (Ctx.getLangOpts().AlignedAllocation && !Ty.isNull() && Ty->isAlignValT())
+ if (Ctx.getLangOpts().AlignedAllocation && !Ty.isNull() && Ty->isAlignValT()) {
+ if (IsAligned)
+ *IsAligned = true;
Consume();
+ }
// Finally, if this is not a sized delete, the final parameter can
// be a 'const std::nothrow_t&'.
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 9f87fe12a9cd..07d128ba555b 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -1417,11 +1417,8 @@ CXXDestructorDecl *CXXRecordDecl::getDestructor() const {
Context.getCanonicalType(ClassType));
DeclContext::lookup_result R = lookup(Name);
- if (R.empty())
- return nullptr;
- CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(R.front());
- return Dtor;
+ return R.empty() ? nullptr : dyn_cast<CXXDestructorDecl>(R.front());
}
bool CXXRecordDecl::isAnyDestructorNoReturn() const {
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index c21cd3f65bd4..afc7fa8ea094 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -1641,25 +1641,32 @@ const char *CastExpr::getCastKindName() const {
llvm_unreachable("Unhandled cast kind!");
}
+namespace {
+ Expr *skipImplicitTemporary(Expr *expr) {
+ // Skip through reference binding to temporary.
+ if (MaterializeTemporaryExpr *Materialize
+ = dyn_cast<MaterializeTemporaryExpr>(expr))
+ expr = Materialize->GetTemporaryExpr();
+
+ // Skip any temporary bindings; they're implicit.
+ if (CXXBindTemporaryExpr *Binder = dyn_cast<CXXBindTemporaryExpr>(expr))
+ expr = Binder->getSubExpr();
+
+ return expr;
+ }
+}
+
Expr *CastExpr::getSubExprAsWritten() {
Expr *SubExpr = nullptr;
CastExpr *E = this;
do {
- SubExpr = E->getSubExpr();
+ SubExpr = skipImplicitTemporary(E->getSubExpr());
- // Skip through reference binding to temporary.
- if (MaterializeTemporaryExpr *Materialize
- = dyn_cast<MaterializeTemporaryExpr>(SubExpr))
- SubExpr = Materialize->GetTemporaryExpr();
-
- // Skip any temporary bindings; they're implicit.
- if (CXXBindTemporaryExpr *Binder = dyn_cast<CXXBindTemporaryExpr>(SubExpr))
- SubExpr = Binder->getSubExpr();
-
// Conversions by constructor and conversion functions have a
// subexpression describing the call; strip it off.
if (E->getCastKind() == CK_ConstructorConversion)
- SubExpr = cast<CXXConstructExpr>(SubExpr)->getArg(0);
+ SubExpr =
+ skipImplicitTemporary(cast<CXXConstructExpr>(SubExpr)->getArg(0));
else if (E->getCastKind() == CK_UserDefinedConversion) {
assert((isa<CXXMemberCallExpr>(SubExpr) ||
isa<BlockExpr>(SubExpr)) &&
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 768947d00ac4..e836135cf2f9 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -6226,10 +6226,6 @@ bool RecordExprEvaluator::VisitInitListExpr(const InitListExpr *E) {
// the initializer list.
ImplicitValueInitExpr VIE(HaveInit ? Info.Ctx.IntTy : Field->getType());
const Expr *Init = HaveInit ? E->getInit(ElementNo++) : &VIE;
- if (Init->isValueDependent()) {
- Success = false;
- continue;
- }
// Temporarily override This, in case there's a CXXDefaultInitExpr in here.
ThisOverrideRAII ThisOverride(*Info.CurrentCall, &This,
@@ -9940,8 +9936,7 @@ static bool EvaluateAsRValue(EvalInfo &Info, const Expr *E, APValue &Result) {
}
static bool FastEvaluateAsRValue(const Expr *Exp, Expr::EvalResult &Result,
- const ASTContext &Ctx, bool &IsConst,
- bool IsCheckingForOverflow) {
+ const ASTContext &Ctx, bool &IsConst) {
// Fast-path evaluations of integer literals, since we sometimes see files
// containing vast quantities of these.
if (const IntegerLiteral *L = dyn_cast<IntegerLiteral>(Exp)) {
@@ -9962,7 +9957,7 @@ static bool FastEvaluateAsRValue(const Expr *Exp, Expr::EvalResult &Result,
// performance problems. Only do so in C++11 for now.
if (Exp->isRValue() && (Exp->getType()->isArrayType() ||
Exp->getType()->isRecordType()) &&
- !Ctx.getLangOpts().CPlusPlus11 && !IsCheckingForOverflow) {
+ !Ctx.getLangOpts().CPlusPlus11) {
IsConst = false;
return true;
}
@@ -9977,7 +9972,7 @@ static bool FastEvaluateAsRValue(const Expr *Exp, Expr::EvalResult &Result,
/// will be applied to the result.
bool Expr::EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx) const {
bool IsConst;
- if (FastEvaluateAsRValue(this, Result, Ctx, IsConst, false))
+ if (FastEvaluateAsRValue(this, Result, Ctx, IsConst))
return IsConst;
EvalInfo Info(Ctx, Result, EvalInfo::EM_IgnoreSideEffects);
@@ -10102,7 +10097,7 @@ APSInt Expr::EvaluateKnownConstInt(const ASTContext &Ctx,
void Expr::EvaluateForOverflow(const ASTContext &Ctx) const {
bool IsConst;
EvalResult EvalResult;
- if (!FastEvaluateAsRValue(this, EvalResult, Ctx, IsConst, true)) {
+ if (!FastEvaluateAsRValue(this, EvalResult, Ctx, IsConst)) {
EvalInfo Info(Ctx, EvalResult, EvalInfo::EM_EvaluateForOverflow);
(void)::EvaluateAsRValue(Info, this, EvalResult.Val);
}
diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp
index cc7a6941f63a..3a899bdbb6d2 100644
--- a/lib/AST/MicrosoftMangle.cpp
+++ b/lib/AST/MicrosoftMangle.cpp
@@ -966,16 +966,71 @@ void MicrosoftCXXNameMangler::mangleNestedName(const NamedDecl *ND) {
}
if (const BlockDecl *BD = dyn_cast<BlockDecl>(DC)) {
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID =
- Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle a local inside this block yet");
- Diags.Report(BD->getLocation(), DiagID);
-
- // FIXME: This is completely, utterly, wrong; see ItaniumMangle
- // for how this should be done.
- Out << "__block_invoke" << Context.getBlockId(BD, false);
- Out << '@';
+ auto Discriminate =
+ [](StringRef Name, const unsigned Discriminator,
+ const unsigned ParameterDiscriminator) -> std::string {
+ std::string Buffer;
+ llvm::raw_string_ostream Stream(Buffer);
+ Stream << Name;
+ if (Discriminator)
+ Stream << '_' << Discriminator;
+ if (ParameterDiscriminator)
+ Stream << '_' << ParameterDiscriminator;
+ return Stream.str();
+ };
+
+ unsigned Discriminator = BD->getBlockManglingNumber();
+ if (!Discriminator)
+ Discriminator = Context.getBlockId(BD, /*Local=*/false);
+
+ // Mangle the parameter position as a discriminator to deal with unnamed
+ // parameters. Rather than mangling the unqualified parameter name,
+ // always use the position to give a uniform mangling.
+ unsigned ParameterDiscriminator = 0;
+ if (const auto *MC = BD->getBlockManglingContextDecl())
+ if (const auto *P = dyn_cast<ParmVarDecl>(MC))
+ if (const auto *F = dyn_cast<FunctionDecl>(P->getDeclContext()))
+ ParameterDiscriminator =
+ F->getNumParams() - P->getFunctionScopeIndex();
+
+ DC = getEffectiveDeclContext(BD);
+
+ Out << '?';
+ mangleSourceName(Discriminate("_block_invoke", Discriminator,
+ ParameterDiscriminator));
+ // If we have a block mangling context, encode that now. This allows us
+ // to discriminate between named static data initializers in the same
+ // scope. This is handled differently from parameters, which use
+ // positions to discriminate between multiple instances.
+ if (const auto *MC = BD->getBlockManglingContextDecl())
+ if (!isa<ParmVarDecl>(MC))
+ if (const auto *ND = dyn_cast<NamedDecl>(MC))
+ mangleUnqualifiedName(ND);
+ // MS ABI and Itanium manglings are in inverted scopes. In the case of a
+ // RecordDecl, mangle the entire scope hierachy at this point rather than
+ // just the unqualified name to get the ordering correct.
+ if (const auto *RD = dyn_cast<RecordDecl>(DC))
+ mangleName(RD);
+ else
+ Out << '@';
+ // void __cdecl
+ Out << "YAX";
+ // struct __block_literal *
+ Out << 'P';
+ // __ptr64
+ if (PointersAre64Bit)
+ Out << 'E';
+ Out << 'A';
+ mangleArtificalTagType(TTK_Struct,
+ Discriminate("__block_literal", Discriminator,
+ ParameterDiscriminator));
+ Out << "@Z";
+
+ // If the effective context was a Record, we have fully mangled the
+ // qualified name and do not need to continue.
+ if (isa<RecordDecl>(DC))
+ break;
+ continue;
} else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC)) {
mangleObjCMethodName(Method);
} else if (isa<NamedDecl>(DC)) {
diff --git a/lib/AST/ODRHash.cpp b/lib/AST/ODRHash.cpp
index 05bed658f3fc..3f66e58eb868 100644
--- a/lib/AST/ODRHash.cpp
+++ b/lib/AST/ODRHash.cpp
@@ -82,25 +82,13 @@ void ODRHash::AddDeclarationName(DeclarationName Name) {
}
void ODRHash::AddNestedNameSpecifier(const NestedNameSpecifier *NNS) {
- // Unlike the other pointer handling functions, allow null pointers here.
- if (!NNS) {
- AddBoolean(false);
- return;
+ assert(NNS && "Expecting non-null pointer.");
+ const auto *Prefix = NNS->getPrefix();
+ AddBoolean(Prefix);
+ if (Prefix) {
+ AddNestedNameSpecifier(Prefix);
}
-
- // Skip inlined namespaces.
auto Kind = NNS->getKind();
- if (Kind == NestedNameSpecifier::Namespace) {
- if (NNS->getAsNamespace()->isInline()) {
- return AddNestedNameSpecifier(NNS->getPrefix());
- }
- }
-
- AddBoolean(true);
-
- // Process prefix
- AddNestedNameSpecifier(NNS->getPrefix());
-
ID.AddInteger(Kind);
switch (Kind) {
case NestedNameSpecifier::Identifier:
@@ -146,7 +134,10 @@ void ODRHash::AddTemplateArgument(TemplateArgument TA) {
switch (Kind) {
case TemplateArgument::Null:
+ llvm_unreachable("Expected valid TemplateArgument");
case TemplateArgument::Type:
+ AddQualType(TA.getAsType());
+ break;
case TemplateArgument::Declaration:
case TemplateArgument::NullPtr:
case TemplateArgument::Integral:
@@ -430,8 +421,18 @@ public:
Hash.AddQualType(T);
}
+ void AddType(const Type *T) {
+ Hash.AddBoolean(T);
+ if (T) {
+ Hash.AddType(T);
+ }
+ }
+
void AddNestedNameSpecifier(const NestedNameSpecifier *NNS) {
- Hash.AddNestedNameSpecifier(NNS);
+ Hash.AddBoolean(NNS);
+ if (NNS) {
+ Hash.AddNestedNameSpecifier(NNS);
+ }
}
void AddIdentifierInfo(const IdentifierInfo *II) {
@@ -517,7 +518,13 @@ public:
void VisitTypedefType(const TypedefType *T) {
AddDecl(T->getDecl());
- AddQualType(T->getDecl()->getUnderlyingType().getCanonicalType());
+ QualType UnderlyingType = T->getDecl()->getUnderlyingType();
+ VisitQualifiers(UnderlyingType.getQualifiers());
+ while (const TypedefType *Underlying =
+ dyn_cast<TypedefType>(UnderlyingType.getTypePtr())) {
+ UnderlyingType = Underlying->getDecl()->getUnderlyingType();
+ }
+ AddType(UnderlyingType.getTypePtr());
VisitType(T);
}
diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp
index cf981be0a4dd..c0b9cadca422 100644
--- a/lib/AST/RecordLayoutBuilder.cpp
+++ b/lib/AST/RecordLayoutBuilder.cpp
@@ -3073,6 +3073,41 @@ uint64_t ASTContext::getFieldOffset(const ValueDecl *VD) const {
return OffsetInBits;
}
+uint64_t ASTContext::lookupFieldBitOffset(const ObjCInterfaceDecl *OID,
+ const ObjCImplementationDecl *ID,
+ const ObjCIvarDecl *Ivar) const {
+ const ObjCInterfaceDecl *Container = Ivar->getContainingInterface();
+
+ // FIXME: We should eliminate the need to have ObjCImplementationDecl passed
+ // in here; it should never be necessary because that should be the lexical
+ // decl context for the ivar.
+
+ // If we know have an implementation (and the ivar is in it) then
+ // look up in the implementation layout.
+ const ASTRecordLayout *RL;
+ if (ID && declaresSameEntity(ID->getClassInterface(), Container))
+ RL = &getASTObjCImplementationLayout(ID);
+ else
+ RL = &getASTObjCInterfaceLayout(Container);
+
+ // Compute field index.
+ //
+ // FIXME: The index here is closely tied to how ASTContext::getObjCLayout is
+ // implemented. This should be fixed to get the information from the layout
+ // directly.
+ unsigned Index = 0;
+
+ for (const ObjCIvarDecl *IVD = Container->all_declared_ivar_begin();
+ IVD; IVD = IVD->getNextIvar()) {
+ if (Ivar == IVD)
+ break;
+ ++Index;
+ }
+ assert(Index < RL->getFieldCount() && "Ivar is not inside record layout!");
+
+ return RL->getFieldOffset(Index);
+}
+
/// getObjCLayout - Get or compute information about the layout of the
/// given interface.
///
diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp
index 99a25f342526..f1fbe2806b5d 100644
--- a/lib/AST/StmtProfile.cpp
+++ b/lib/AST/StmtProfile.cpp
@@ -186,7 +186,10 @@ namespace {
Hash.AddTemplateName(Name);
}
void VisitNestedNameSpecifier(NestedNameSpecifier *NNS) override {
- Hash.AddNestedNameSpecifier(NNS);
+ ID.AddBoolean(NNS);
+ if (NNS) {
+ Hash.AddNestedNameSpecifier(NNS);
+ }
}
};
}
diff --git a/lib/Basic/SourceLocation.cpp b/lib/Basic/SourceLocation.cpp
index a58d0465a6f4..89ddbc946a49 100644
--- a/lib/Basic/SourceLocation.cpp
+++ b/lib/Basic/SourceLocation.cpp
@@ -92,6 +92,76 @@ FullSourceLoc FullSourceLoc::getSpellingLoc() const {
return FullSourceLoc(SrcMgr->getSpellingLoc(*this), *SrcMgr);
}
+FullSourceLoc FullSourceLoc::getFileLoc() const {
+ assert(isValid());
+ return FullSourceLoc(SrcMgr->getFileLoc(*this), *SrcMgr);
+}
+
+std::pair<FullSourceLoc, FullSourceLoc>
+FullSourceLoc::getImmediateExpansionRange() const {
+ assert(isValid());
+ std::pair<SourceLocation, SourceLocation> Range =
+ SrcMgr->getImmediateExpansionRange(*this);
+ return std::make_pair(FullSourceLoc(Range.first, *SrcMgr),
+ FullSourceLoc(Range.second, *SrcMgr));
+}
+
+PresumedLoc FullSourceLoc::getPresumedLoc(bool UseLineDirectives) const {
+ if (!isValid())
+ return PresumedLoc();
+
+ return SrcMgr->getPresumedLoc(*this, UseLineDirectives);
+}
+
+bool FullSourceLoc::isMacroArgExpansion(FullSourceLoc *StartLoc) const {
+ assert(isValid());
+ return SrcMgr->isMacroArgExpansion(*this, StartLoc);
+}
+
+FullSourceLoc FullSourceLoc::getImmediateMacroCallerLoc() const {
+ assert(isValid());
+ return FullSourceLoc(SrcMgr->getImmediateMacroCallerLoc(*this), *SrcMgr);
+}
+
+std::pair<FullSourceLoc, StringRef> FullSourceLoc::getModuleImportLoc() const {
+ if (!isValid())
+ return std::make_pair(FullSourceLoc(), StringRef());
+
+ std::pair<SourceLocation, StringRef> ImportLoc =
+ SrcMgr->getModuleImportLoc(*this);
+ return std::make_pair(FullSourceLoc(ImportLoc.first, *SrcMgr),
+ ImportLoc.second);
+}
+
+unsigned FullSourceLoc::getFileOffset() const {
+ assert(isValid());
+ return SrcMgr->getFileOffset(*this);
+}
+
+unsigned FullSourceLoc::getLineNumber(bool *Invalid) const {
+ assert(isValid());
+ return SrcMgr->getLineNumber(getFileID(), getFileOffset(), Invalid);
+}
+
+unsigned FullSourceLoc::getColumnNumber(bool *Invalid) const {
+ assert(isValid());
+ return SrcMgr->getColumnNumber(getFileID(), getFileOffset(), Invalid);
+}
+
+std::pair<FullSourceLoc, FullSourceLoc>
+FullSourceLoc::getExpansionRange() const {
+ assert(isValid());
+ std::pair<SourceLocation, SourceLocation> Range =
+ SrcMgr->getExpansionRange(*this);
+ return std::make_pair(FullSourceLoc(Range.first, *SrcMgr),
+ FullSourceLoc(Range.second, *SrcMgr));
+}
+
+const FileEntry *FullSourceLoc::getFileEntry() const {
+ assert(isValid());
+ return SrcMgr->getFileEntryForID(getFileID());
+}
+
unsigned FullSourceLoc::getExpansionLineNumber(bool *Invalid) const {
assert(isValid());
return SrcMgr->getExpansionLineNumber(*this, Invalid);
diff --git a/lib/Basic/SourceManager.cpp b/lib/Basic/SourceManager.cpp
index 3936afab21a4..f0b53b4e48a5 100644
--- a/lib/Basic/SourceManager.cpp
+++ b/lib/Basic/SourceManager.cpp
@@ -2018,9 +2018,51 @@ bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS,
if (LOffs.first.isInvalid() || ROffs.first.isInvalid())
return LOffs.first.isInvalid() && !ROffs.first.isInvalid();
+ std::pair<bool, bool> InSameTU = isInTheSameTranslationUnit(LOffs, ROffs);
+ if (InSameTU.first)
+ return InSameTU.second;
+
+ // If we arrived here, the location is either in a built-ins buffer or
+ // associated with global inline asm. PR5662 and PR22576 are examples.
+
+ StringRef LB = getBuffer(LOffs.first)->getBufferIdentifier();
+ StringRef RB = getBuffer(ROffs.first)->getBufferIdentifier();
+ bool LIsBuiltins = LB == "<built-in>";
+ bool RIsBuiltins = RB == "<built-in>";
+ // Sort built-in before non-built-in.
+ if (LIsBuiltins || RIsBuiltins) {
+ if (LIsBuiltins != RIsBuiltins)
+ return LIsBuiltins;
+ // Both are in built-in buffers, but from different files. We just claim that
+ // lower IDs come first.
+ return LOffs.first < ROffs.first;
+ }
+ bool LIsAsm = LB == "<inline asm>";
+ bool RIsAsm = RB == "<inline asm>";
+ // Sort assembler after built-ins, but before the rest.
+ if (LIsAsm || RIsAsm) {
+ if (LIsAsm != RIsAsm)
+ return RIsAsm;
+ assert(LOffs.first == ROffs.first);
+ return false;
+ }
+ bool LIsScratch = LB == "<scratch space>";
+ bool RIsScratch = RB == "<scratch space>";
+ // Sort scratch after inline asm, but before the rest.
+ if (LIsScratch || RIsScratch) {
+ if (LIsScratch != RIsScratch)
+ return LIsScratch;
+ return LOffs.second < ROffs.second;
+ }
+ llvm_unreachable("Unsortable locations found");
+}
+
+std::pair<bool, bool> SourceManager::isInTheSameTranslationUnit(
+ std::pair<FileID, unsigned> &LOffs,
+ std::pair<FileID, unsigned> &ROffs) const {
// If the source locations are in the same file, just compare offsets.
if (LOffs.first == ROffs.first)
- return LOffs.second < ROffs.second;
+ return std::make_pair(true, LOffs.second < ROffs.second);
// If we are comparing a source location with multiple locations in the same
// file, we get a big win by caching the result.
@@ -2030,7 +2072,8 @@ bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS,
// If we are comparing a source location with multiple locations in the same
// file, we get a big win by caching the result.
if (IsBeforeInTUCache.isCacheValid(LOffs.first, ROffs.first))
- return IsBeforeInTUCache.getCachedResult(LOffs.second, ROffs.second);
+ return std::make_pair(
+ true, IsBeforeInTUCache.getCachedResult(LOffs.second, ROffs.second));
// Okay, we missed in the cache, start updating the cache for this query.
IsBeforeInTUCache.setQueryFIDs(LOffs.first, ROffs.first,
@@ -2060,44 +2103,12 @@ bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS,
// locations within the common file and cache them.
if (LOffs.first == ROffs.first) {
IsBeforeInTUCache.setCommonLoc(LOffs.first, LOffs.second, ROffs.second);
- return IsBeforeInTUCache.getCachedResult(LOffs.second, ROffs.second);
+ return std::make_pair(
+ true, IsBeforeInTUCache.getCachedResult(LOffs.second, ROffs.second));
}
-
- // If we arrived here, the location is either in a built-ins buffer or
- // associated with global inline asm. PR5662 and PR22576 are examples.
-
// Clear the lookup cache, it depends on a common location.
IsBeforeInTUCache.clear();
- StringRef LB = getBuffer(LOffs.first)->getBufferIdentifier();
- StringRef RB = getBuffer(ROffs.first)->getBufferIdentifier();
- bool LIsBuiltins = LB == "<built-in>";
- bool RIsBuiltins = RB == "<built-in>";
- // Sort built-in before non-built-in.
- if (LIsBuiltins || RIsBuiltins) {
- if (LIsBuiltins != RIsBuiltins)
- return LIsBuiltins;
- // Both are in built-in buffers, but from different files. We just claim that
- // lower IDs come first.
- return LOffs.first < ROffs.first;
- }
- bool LIsAsm = LB == "<inline asm>";
- bool RIsAsm = RB == "<inline asm>";
- // Sort assembler after built-ins, but before the rest.
- if (LIsAsm || RIsAsm) {
- if (LIsAsm != RIsAsm)
- return RIsAsm;
- assert(LOffs.first == ROffs.first);
- return false;
- }
- bool LIsScratch = LB == "<scratch space>";
- bool RIsScratch = RB == "<scratch space>";
- // Sort scratch after inline asm, but before the rest.
- if (LIsScratch || RIsScratch) {
- if (LIsScratch != RIsScratch)
- return LIsScratch;
- return LOffs.second < ROffs.second;
- }
- llvm_unreachable("Unsortable locations found");
+ return std::make_pair(false, false);
}
void SourceManager::PrintStats() const {
diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp
index c5af99e4b6af..4f04489a4a10 100644
--- a/lib/Basic/Targets.cpp
+++ b/lib/Basic/Targets.cpp
@@ -2706,7 +2706,7 @@ class X86TargetInfo : public TargetInfo {
CK_C3_2,
/// This enumerator is a bit odd, as GCC no longer accepts -march=yonah.
- /// Clang however has some logic to suport this.
+ /// Clang however has some logic to support this.
// FIXME: Warn, deprecate, and potentially remove this.
CK_Yonah,
//@}
@@ -2737,6 +2737,7 @@ class X86TargetInfo : public TargetInfo {
//@{
CK_Bonnell,
CK_Silvermont,
+ CK_Goldmont,
//@}
/// \name Nehalem
@@ -2878,6 +2879,7 @@ class X86TargetInfo : public TargetInfo {
.Case("atom", CK_Bonnell) // Legacy name.
.Case("silvermont", CK_Silvermont)
.Case("slm", CK_Silvermont) // Legacy name.
+ .Case("goldmont", CK_Goldmont)
.Case("nehalem", CK_Nehalem)
.Case("corei7", CK_Nehalem) // Legacy name.
.Case("westmere", CK_Westmere)
@@ -3093,6 +3095,7 @@ public:
case CK_Penryn:
case CK_Bonnell:
case CK_Silvermont:
+ case CK_Goldmont:
case CK_Nehalem:
case CK_Westmere:
case CK_SandyBridge:
@@ -3221,7 +3224,6 @@ bool X86TargetInfo::initFeatureMap(
setFeatureEnabledImpl(Features, "cx16", true);
break;
case CK_Core2:
- case CK_Bonnell:
setFeatureEnabledImpl(Features, "ssse3", true);
setFeatureEnabledImpl(Features, "fxsr", true);
setFeatureEnabledImpl(Features, "cx16", true);
@@ -3276,7 +3278,6 @@ bool X86TargetInfo::initFeatureMap(
setFeatureEnabledImpl(Features, "xsaveopt", true);
LLVM_FALLTHROUGH;
case CK_Westmere:
- case CK_Silvermont:
setFeatureEnabledImpl(Features, "aes", true);
setFeatureEnabledImpl(Features, "pclmul", true);
LLVM_FALLTHROUGH;
@@ -3285,6 +3286,28 @@ bool X86TargetInfo::initFeatureMap(
setFeatureEnabledImpl(Features, "fxsr", true);
setFeatureEnabledImpl(Features, "cx16", true);
break;
+ case CK_Goldmont:
+ setFeatureEnabledImpl(Features, "sha", true);
+ setFeatureEnabledImpl(Features, "rdrnd", true);
+ setFeatureEnabledImpl(Features, "rdseed", true);
+ setFeatureEnabledImpl(Features, "xsave", true);
+ setFeatureEnabledImpl(Features, "xsaveopt", true);
+ setFeatureEnabledImpl(Features, "xsavec", true);
+ setFeatureEnabledImpl(Features, "xsaves", true);
+ setFeatureEnabledImpl(Features, "clflushopt", true);
+ setFeatureEnabledImpl(Features, "mpx", true);
+ LLVM_FALLTHROUGH;
+ case CK_Silvermont:
+ setFeatureEnabledImpl(Features, "aes", true);
+ setFeatureEnabledImpl(Features, "pclmul", true);
+ setFeatureEnabledImpl(Features, "sse4.2", true);
+ LLVM_FALLTHROUGH;
+ case CK_Bonnell:
+ setFeatureEnabledImpl(Features, "movbe", true);
+ setFeatureEnabledImpl(Features, "ssse3", true);
+ setFeatureEnabledImpl(Features, "fxsr", true);
+ setFeatureEnabledImpl(Features, "cx16", true);
+ break;
case CK_KNL:
setFeatureEnabledImpl(Features, "avx512f", true);
setFeatureEnabledImpl(Features, "avx512cd", true);
@@ -3524,6 +3547,7 @@ void X86TargetInfo::setSSELevel(llvm::StringMap<bool> &Features,
Features["avx512pf"] = Features["avx512dq"] = Features["avx512bw"] =
Features["avx512vl"] = Features["avx512vbmi"] =
Features["avx512ifma"] = Features["avx512vpopcntdq"] = false;
+ break;
}
}
@@ -3556,6 +3580,7 @@ void X86TargetInfo::setMMXLevel(llvm::StringMap<bool> &Features,
LLVM_FALLTHROUGH;
case AMD3DNowAthlon:
Features["3dnowa"] = false;
+ break;
}
}
@@ -3590,6 +3615,7 @@ void X86TargetInfo::setXOPLevel(llvm::StringMap<bool> &Features, XOPEnum Level,
LLVM_FALLTHROUGH;
case XOP:
Features["xop"] = false;
+ break;
}
}
@@ -3893,6 +3919,9 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts,
case CK_Silvermont:
defineCPUMacros(Builder, "slm");
break;
+ case CK_Goldmont:
+ defineCPUMacros(Builder, "goldmont");
+ break;
case CK_Nehalem:
case CK_Westmere:
case CK_SandyBridge:
@@ -4156,6 +4185,7 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts,
break;
default:
Builder.defineMacro("_M_IX86_FP", Twine(0));
+ break;
}
}
@@ -5413,7 +5443,7 @@ public:
if (Triple.getOS() == llvm::Triple::Linux ||
Triple.getOS() == llvm::Triple::UnknownOS)
this->MCountName =
- Opts.EABIVersion == "gnu" ? "\01__gnu_mcount_nc" : "\01mcount";
+ Opts.EABIVersion == llvm::EABI::GNU ? "\01__gnu_mcount_nc" : "\01mcount";
}
StringRef getABI() const override { return ABI; }
@@ -5594,6 +5624,17 @@ public:
bool setFPMath(StringRef Name) override;
+ void getTargetDefinesARMV81A(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ Builder.defineMacro("__ARM_FEATURE_QRDMX", "1");
+ }
+
+ void getTargetDefinesARMV82A(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ // Also include the ARMv8.1-A defines
+ getTargetDefinesARMV81A(Opts, Builder);
+ }
+
void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override {
// Target identification.
@@ -5792,8 +5833,15 @@ public:
if (Opts.UnsafeFPMath)
Builder.defineMacro("__ARM_FP_FAST", "1");
- if (ArchKind == llvm::ARM::AK_ARMV8_1A)
- Builder.defineMacro("__ARM_FEATURE_QRDMX", "1");
+ switch(ArchKind) {
+ default: break;
+ case llvm::ARM::AK_ARMV8_1A:
+ getTargetDefinesARMV81A(Opts, Builder);
+ break;
+ case llvm::ARM::AK_ARMV8_2A:
+ getTargetDefinesARMV82A(Opts, Builder);
+ break;
+ }
}
ArrayRef<Builtin::Info> getTargetBuiltins() const override {
@@ -6186,9 +6234,8 @@ class AArch64TargetInfo : public TargetInfo {
unsigned CRC;
unsigned Crypto;
unsigned Unaligned;
- unsigned V8_1A;
- unsigned V8_2A;
unsigned HasFullFP16;
+ llvm::AArch64::ArchKind ArchKind;
static const Builtin::Info BuiltinInfo[];
@@ -6236,7 +6283,7 @@ public:
if (Triple.getOS() == llvm::Triple::Linux)
this->MCountName = "\01_mcount";
else if (Triple.getOS() == llvm::Triple::UnknownOS)
- this->MCountName = Opts.EABIVersion == "gnu" ? "\01_mcount" : "mcount";
+ this->MCountName = Opts.EABIVersion == llvm::EABI::GNU ? "\01_mcount" : "mcount";
}
StringRef getABI() const override { return ABI; }
@@ -6254,6 +6301,20 @@ public:
static_cast<unsigned>(llvm::AArch64::ArchKind::AK_INVALID);
}
+ void getTargetDefinesARMV81A(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ Builder.defineMacro("__ARM_FEATURE_QRDMX", "1");
+ }
+
+ void getTargetDefinesARMV82A(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ // Also include the ARMv8.1 defines
+ getTargetDefinesARMV81A(Opts, Builder);
+
+ if (FPU == NeonMode && HasFullFP16)
+ Builder.defineMacro("__ARM_FEATURE_FP16_VECTOR_ARITHMETIC", "1");
+ }
+
void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override {
// Target identification.
@@ -6318,10 +6379,15 @@ public:
if (Unaligned)
Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1");
- if (V8_1A)
- Builder.defineMacro("__ARM_FEATURE_QRDMX", "1");
- if (V8_2A && FPU == NeonMode && HasFullFP16)
- Builder.defineMacro("__ARM_FEATURE_FP16_VECTOR_ARITHMETIC", "1");
+ switch(ArchKind) {
+ default: break;
+ case llvm::AArch64::ArchKind::AK_ARMV8_1A:
+ getTargetDefinesARMV81A(Opts, Builder);
+ break;
+ case llvm::AArch64::ArchKind::AK_ARMV8_2A:
+ getTargetDefinesARMV82A(Opts, Builder);
+ break;
+ }
// All of the __sync_(bool|val)_compare_and_swap_(1|2|4|8) builtins work.
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
@@ -6348,9 +6414,8 @@ public:
CRC = 0;
Crypto = 0;
Unaligned = 1;
- V8_1A = 0;
- V8_2A = 0;
HasFullFP16 = 0;
+ ArchKind = llvm::AArch64::ArchKind::AK_ARMV8A;
for (const auto &Feature : Features) {
if (Feature == "+neon")
@@ -6362,9 +6427,9 @@ public:
if (Feature == "+strict-align")
Unaligned = 0;
if (Feature == "+v8.1a")
- V8_1A = 1;
+ ArchKind = llvm::AArch64::ArchKind::AK_ARMV8_1A;
if (Feature == "+v8.2a")
- V8_2A = 1;
+ ArchKind = llvm::AArch64::ArchKind::AK_ARMV8_2A;
if (Feature == "+fullfp16")
HasFullFP16 = 1;
}
@@ -6550,6 +6615,43 @@ public:
}
};
+class MicrosoftARM64TargetInfo
+ : public WindowsTargetInfo<AArch64leTargetInfo> {
+ const llvm::Triple Triple;
+
+public:
+ MicrosoftARM64TargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts)
+ : WindowsTargetInfo<AArch64leTargetInfo>(Triple, Opts), Triple(Triple) {
+ WCharType = UnsignedShort;
+ SizeType = UnsignedLongLong;
+ TheCXXABI.set(TargetCXXABI::Microsoft);
+ }
+
+ void setDataLayout() override {
+ resetDataLayout("e-m:w-i64:64-i128:128-n32:64-S128");
+ }
+
+ void getVisualStudioDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ WindowsTargetInfo<AArch64leTargetInfo>::getVisualStudioDefines(Opts,
+ Builder);
+ Builder.defineMacro("_WIN32", "1");
+ Builder.defineMacro("_WIN64", "1");
+ Builder.defineMacro("_M_ARM64", "1");
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
+ WindowsTargetInfo::getTargetDefines(Opts, Builder);
+ getVisualStudioDefines(Opts, Builder);
+ }
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::CharPtrBuiltinVaList;
+ }
+};
+
class AArch64beTargetInfo : public AArch64TargetInfo {
void setDataLayout() override {
assert(!getTriple().isOSBinFormatMachO());
@@ -7727,6 +7829,148 @@ public:
}
};
+class Nios2TargetInfo : public TargetInfo {
+ void setDataLayout() {
+ if (BigEndian)
+ resetDataLayout("E-p:32:32:32-i8:8:32-i16:16:32-n32");
+ else
+ resetDataLayout("e-p:32:32:32-i8:8:32-i16:16:32-n32");
+ }
+
+ static const Builtin::Info BuiltinInfo[];
+ std::string CPU;
+ std::string ABI;
+
+public:
+ Nios2TargetInfo(const llvm::Triple &triple, const TargetOptions &opts)
+ : TargetInfo(triple), CPU(opts.CPU), ABI(opts.ABI) {
+ SizeType = UnsignedInt;
+ PtrDiffType = SignedInt;
+ MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32;
+ setDataLayout();
+ }
+
+ StringRef getABI() const override { return ABI; }
+ bool setABI(const std::string &Name) override {
+ if (Name == "o32" || Name == "eabi") {
+ ABI = Name;
+ return true;
+ }
+ return false;
+ }
+
+ bool setCPU(const std::string &Name) override {
+ if (Name == "nios2r1" || Name == "nios2r2") {
+ CPU = Name;
+ return true;
+ }
+ return false;
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
+ DefineStd(Builder, "nios2", Opts);
+ DefineStd(Builder, "NIOS2", Opts);
+
+ Builder.defineMacro("__nios2");
+ Builder.defineMacro("__NIOS2");
+ Builder.defineMacro("__nios2__");
+ Builder.defineMacro("__NIOS2__");
+ }
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override {
+ return llvm::makeArrayRef(BuiltinInfo, clang::Nios2::LastTSBuiltin -
+ Builtin::FirstTSBuiltin);
+ }
+
+ bool isFeatureSupportedByCPU(StringRef Feature, StringRef CPU) const {
+ const bool isR2 = CPU == "nios2r2";
+ return llvm::StringSwitch<bool>(Feature)
+ .Case("nios2r2mandatory", isR2)
+ .Case("nios2r2bmx", isR2)
+ .Case("nios2r2mpx", isR2)
+ .Case("nios2r2cdx", isR2)
+ .Default(false);
+ }
+
+ bool initFeatureMap(llvm::StringMap<bool> &Features,
+ DiagnosticsEngine &Diags, StringRef CPU,
+ const std::vector<std::string> &FeatureVec) const override {
+ static const char *allFeatures[] = {
+ "nios2r2mandatory", "nios2r2bmx", "nios2r2mpx", "nios2r2cdx"
+ };
+ for (const char *feature : allFeatures) {
+ Features[feature] = isFeatureSupportedByCPU(feature, CPU);
+ }
+ return true;
+ }
+
+ bool hasFeature(StringRef Feature) const override {
+ return isFeatureSupportedByCPU(Feature, CPU);
+ }
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::VoidPtrBuiltinVaList;
+ }
+
+ ArrayRef<const char *> getGCCRegNames() const override {
+ static const char *const GCCRegNames[] = {
+ // CPU register names
+ // Must match second column of GCCRegAliases
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",
+ "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20",
+ "r21", "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", "r30",
+ "r31",
+ // Floating point register names
+ "ctl0", "ctl1", "ctl2", "ctl3", "ctl4", "ctl5", "ctl6", "ctl7", "ctl8",
+ "ctl9", "ctl10", "ctl11", "ctl12", "ctl13", "ctl14", "ctl15"
+ };
+ return llvm::makeArrayRef(GCCRegNames);
+ }
+
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &Info) const override {
+ switch (*Name) {
+ default:
+ return false;
+
+ case 'r': // CPU registers.
+ case 'd': // Equivalent to "r" unless generating MIPS16 code.
+ case 'y': // Equivalent to "r", backwards compatibility only.
+ case 'f': // floating-point registers.
+ case 'c': // $25 for indirect jumps
+ case 'l': // lo register
+ case 'x': // hilo register pair
+ Info.setAllowsRegister();
+ return true;
+ }
+ }
+
+ const char *getClobbers() const override { return ""; }
+
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
+ static const TargetInfo::GCCRegAlias aliases[] = {
+ {{"zero"}, "r0"}, {{"at"}, "r1"}, {{"et"}, "r24"},
+ {{"bt"}, "r25"}, {{"gp"}, "r26"}, {{"sp"}, "r27"},
+ {{"fp"}, "r28"}, {{"ea"}, "r29"}, {{"ba"}, "r30"},
+ {{"ra"}, "r31"}, {{"status"}, "ctl0"}, {{"estatus"}, "ctl1"},
+ {{"bstatus"}, "ctl2"}, {{"ienable"}, "ctl3"}, {{"ipending"}, "ctl4"},
+ {{"cpuid"}, "ctl5"}, {{"exception"}, "ctl7"}, {{"pteaddr"}, "ctl8"},
+ {{"tlbacc"}, "ctl9"}, {{"tlbmisc"}, "ctl10"}, {{"badaddr"}, "ctl12"},
+ {{"config"}, "ctl13"}, {{"mpubase"}, "ctl14"}, {{"mpuacc"}, "ctl15"},
+ };
+ return llvm::makeArrayRef(aliases);
+ }
+};
+
+const Builtin::Info Nios2TargetInfo::BuiltinInfo[] = {
+#define BUILTIN(ID, TYPE, ATTRS) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
+#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE},
+#include "clang/Basic/BuiltinsNios2.def"
+};
+
class MipsTargetInfo : public TargetInfo {
void setDataLayout() {
StringRef Layout;
@@ -9264,6 +9508,8 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple,
return new NetBSDTargetInfo<AArch64leTargetInfo>(Triple, Opts);
case llvm::Triple::OpenBSD:
return new OpenBSDTargetInfo<AArch64leTargetInfo>(Triple, Opts);
+ case llvm::Triple::Win32:
+ return new MicrosoftARM64TargetInfo(Triple, Opts);
default:
return new AArch64leTargetInfo(Triple, Opts);
}
@@ -9353,6 +9599,9 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple,
case llvm::Triple::msp430:
return new MSP430TargetInfo(Triple, Opts);
+ case llvm::Triple::nios2:
+ return new LinuxTargetInfo<Nios2TargetInfo>(Triple, Opts);
+
case llvm::Triple::mips:
switch (os) {
case llvm::Triple::Linux:
diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp
index bd01902a032b..9b3850abcce7 100644
--- a/lib/CodeGen/BackendUtil.cpp
+++ b/lib/CodeGen/BackendUtil.cpp
@@ -54,6 +54,7 @@
#include "llvm/Transforms/ObjCARC.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Scalar/GVN.h"
+#include "llvm/Transforms/Utils/NameAnonGlobals.h"
#include "llvm/Transforms/Utils/SymbolRewriter.h"
#include <memory>
using namespace clang;
@@ -414,11 +415,7 @@ static void initTargetOptions(llvm::TargetOptions &Options,
Options.RelaxELFRelocations = CodeGenOpts.RelaxELFRelocations;
// Set EABI version.
- Options.EABIVersion = llvm::StringSwitch<llvm::EABI>(TargetOpts.EABIVersion)
- .Case("4", llvm::EABI::EABI4)
- .Case("5", llvm::EABI::EABI5)
- .Case("gnu", llvm::EABI::GNU)
- .Default(llvm::EABI::Default);
+ Options.EABIVersion = TargetOpts.EABIVersion;
if (LangOpts.SjLjExceptions)
Options.ExceptionModel = llvm::ExceptionHandling::SjLj;
@@ -491,7 +488,6 @@ void EmitAssemblyHelper::CreatePasses(legacy::PassManager &MPM,
PMBuilder.OptLevel = CodeGenOpts.OptimizationLevel;
PMBuilder.SizeLevel = CodeGenOpts.OptimizeSize;
- PMBuilder.BBVectorize = CodeGenOpts.VectorizeBB;
PMBuilder.SLPVectorize = CodeGenOpts.VectorizeSLP;
PMBuilder.LoopVectorize = CodeGenOpts.VectorizeLoop;
@@ -856,11 +852,15 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(
if (CodeGenOpts.hasProfileIRUse())
PGOOpt.ProfileUseFile = CodeGenOpts.ProfileInstrumentUsePath;
+ if (!CodeGenOpts.SampleProfileFile.empty())
+ PGOOpt.SampleProfileFile = CodeGenOpts.SampleProfileFile;
+
// Only pass a PGO options struct if -fprofile-generate or
// -fprofile-use were passed on the cmdline.
PassBuilder PB(TM.get(),
(PGOOpt.RunProfileGen ||
- !PGOOpt.ProfileUseFile.empty()) ?
+ !PGOOpt.ProfileUseFile.empty() ||
+ !PGOOpt.SampleProfileFile.empty()) ?
Optional<PGOOptions>(PGOOpt) : None);
LoopAnalysisManager LAM;
@@ -878,20 +878,34 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(
PB.registerLoopAnalyses(LAM);
PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
- ModulePassManager MPM;
+ ModulePassManager MPM(CodeGenOpts.DebugPassManager);
if (!CodeGenOpts.DisableLLVMPasses) {
+ bool IsThinLTO = CodeGenOpts.EmitSummaryIndex;
+ bool IsLTO = CodeGenOpts.PrepareForLTO;
+
if (CodeGenOpts.OptimizationLevel == 0) {
// Build a minimal pipeline based on the semantics required by Clang,
// which is just that always inlining occurs.
MPM.addPass(AlwaysInlinerPass());
+ if (IsThinLTO)
+ MPM.addPass(NameAnonGlobalPass());
} else {
- // Otherwise, use the default pass pipeline. We also have to map our
- // optimization levels into one of the distinct levels used to configure
- // the pipeline.
+ // Map our optimization levels into one of the distinct levels used to
+ // configure the pipeline.
PassBuilder::OptimizationLevel Level = mapToLevel(CodeGenOpts);
- MPM = PB.buildPerModuleDefaultPipeline(Level);
+ if (IsThinLTO) {
+ MPM = PB.buildThinLTOPreLinkDefaultPipeline(
+ Level, CodeGenOpts.DebugPassManager);
+ MPM.addPass(NameAnonGlobalPass());
+ } else if (IsLTO) {
+ MPM = PB.buildLTOPreLinkDefaultPipeline(Level,
+ CodeGenOpts.DebugPassManager);
+ } else {
+ MPM = PB.buildPerModuleDefaultPipeline(Level,
+ CodeGenOpts.DebugPassManager);
+ }
}
}
diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp
index a6451b7fc3c1..2a6e92e7f3ce 100644
--- a/lib/CodeGen/CGBuiltin.cpp
+++ b/lib/CodeGen/CGBuiltin.cpp
@@ -9372,6 +9372,16 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID,
Value *Callee = CGM.getIntrinsic(Intrinsic::wasm_grow_memory, X->getType());
return Builder.CreateCall(Callee, X);
}
+ case WebAssembly::BI__builtin_wasm_throw: {
+ Value *Tag = EmitScalarExpr(E->getArg(0));
+ Value *Obj = EmitScalarExpr(E->getArg(1));
+ Value *Callee = CGM.getIntrinsic(Intrinsic::wasm_throw);
+ return Builder.CreateCall(Callee, {Tag, Obj});
+ }
+ case WebAssembly::BI__builtin_wasm_rethrow: {
+ Value *Callee = CGM.getIntrinsic(Intrinsic::wasm_rethrow);
+ return Builder.CreateCall(Callee);
+ }
default:
return nullptr;
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index 38d520a2beb0..13a156c7bbd7 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -1297,7 +1297,7 @@ static void CreateCoercedStore(llvm::Value *Src,
// If store is legal, just bitcast the src pointer.
if (SrcSize <= DstSize) {
- Dst = CGF.Builder.CreateBitCast(Dst, llvm::PointerType::getUnqual(SrcTy));
+ Dst = CGF.Builder.CreateElementBitCast(Dst, SrcTy);
BuildAggStore(CGF, Src, Dst, DstIsVolatile);
} else {
// Otherwise do coercion through memory. This is stupid, but
@@ -2412,8 +2412,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
Address AddrToStoreInto = Address::invalid();
if (SrcSize <= DstSize) {
- AddrToStoreInto =
- Builder.CreateBitCast(Ptr, llvm::PointerType::getUnqual(STy));
+ AddrToStoreInto = Builder.CreateElementBitCast(Ptr, STy);
} else {
AddrToStoreInto =
CreateTempAlloca(STy, Alloca.getAlignment(), "coerce");
@@ -3389,6 +3388,14 @@ void CodeGenFunction::EmitCallArgs(
unsigned Idx = LeftToRight ? I : E - I - 1;
CallExpr::const_arg_iterator Arg = ArgRange.begin() + Idx;
unsigned InitialArgSize = Args.size();
+ // If *Arg is an ObjCIndirectCopyRestoreExpr, check that either the types of
+ // the argument and parameter match or the objc method is parameterized.
+ assert((!isa<ObjCIndirectCopyRestoreExpr>(*Arg) ||
+ getContext().hasSameUnqualifiedType((*Arg)->getType(),
+ ArgTypes[Idx]) ||
+ (isa<ObjCMethodDecl>(AC.getDecl()) &&
+ isObjCMethodWithTypeParams(cast<ObjCMethodDecl>(AC.getDecl())))) &&
+ "Argument and parameter types don't match");
EmitCallArg(Args, *Arg, ArgTypes[Idx]);
// In particular, we depend on it being the last arg in Args, and the
// objectsize bits depend on there only being one arg if !LeftToRight.
@@ -3449,7 +3456,6 @@ void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E,
if (const ObjCIndirectCopyRestoreExpr *CRE
= dyn_cast<ObjCIndirectCopyRestoreExpr>(E)) {
assert(getLangOpts().ObjCAutoRefCount);
- assert(getContext().hasSameUnqualifiedType(E->getType(), type));
return emitWritebackArg(*this, args, CRE);
}
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index ccd3b8d513b1..4b656ea4a879 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -1860,6 +1860,10 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg,
lt = Qualifiers::OCL_ExplicitNone;
}
+ // Load objects passed indirectly.
+ if (Arg.isIndirect() && !ArgVal)
+ ArgVal = Builder.CreateLoad(DeclPtr);
+
if (lt == Qualifiers::OCL_Strong) {
if (!isConsumed) {
if (CGM.getCodeGenOpts().OptimizationLevel == 0) {
diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp
index 7976c53d9e98..98435fefbd2e 100644
--- a/lib/CodeGen/CGObjCMac.cpp
+++ b/lib/CodeGen/CGObjCMac.cpp
@@ -1678,7 +1678,10 @@ struct NullReturnState {
/// Complete the null-return operation. It is valid to call this
/// regardless of whether 'init' has been called.
- RValue complete(CodeGenFunction &CGF, RValue result, QualType resultType,
+ RValue complete(CodeGenFunction &CGF,
+ ReturnValueSlot returnSlot,
+ RValue result,
+ QualType resultType,
const CallArgList &CallArgs,
const ObjCMethodDecl *Method) {
// If we never had to do a null-check, just use the raw result.
@@ -1745,7 +1748,8 @@ struct NullReturnState {
// memory or (2) agg values in registers.
if (result.isAggregate()) {
assert(result.isAggregate() && "null init of non-aggregate result?");
- CGF.EmitNullInitialization(result.getAggregateAddress(), resultType);
+ if (!returnSlot.isUnused())
+ CGF.EmitNullInitialization(result.getAggregateAddress(), resultType);
if (contBB) CGF.EmitBlock(contBB);
return result;
}
@@ -2117,11 +2121,11 @@ CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
}
}
- NullReturnState nullReturn;
+ bool RequiresNullCheck = false;
llvm::Constant *Fn = nullptr;
if (CGM.ReturnSlotInterferesWithArgs(MSI.CallInfo)) {
- if (ReceiverCanBeNull) nullReturn.init(CGF, Arg0);
+ if (ReceiverCanBeNull) RequiresNullCheck = true;
Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper)
: ObjCTypes.getSendStretFn(IsSuper);
} else if (CGM.ReturnTypeUsesFPRet(ResultType)) {
@@ -2134,23 +2138,30 @@ CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
// arm64 uses objc_msgSend for stret methods and yet null receiver check
// must be made for it.
if (ReceiverCanBeNull && CGM.ReturnTypeUsesSRet(MSI.CallInfo))
- nullReturn.init(CGF, Arg0);
+ RequiresNullCheck = true;
Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper)
: ObjCTypes.getSendFn(IsSuper);
}
+ // We don't need to emit a null check to zero out an indirect result if the
+ // result is ignored.
+ if (Return.isUnused())
+ RequiresNullCheck = false;
+
// Emit a null-check if there's a consumed argument other than the receiver.
- bool RequiresNullCheck = false;
- if (ReceiverCanBeNull && CGM.getLangOpts().ObjCAutoRefCount && Method) {
+ if (!RequiresNullCheck && CGM.getLangOpts().ObjCAutoRefCount && Method) {
for (const auto *ParamDecl : Method->parameters()) {
if (ParamDecl->hasAttr<NSConsumedAttr>()) {
- if (!nullReturn.NullBB)
- nullReturn.init(CGF, Arg0);
RequiresNullCheck = true;
break;
}
}
}
+
+ NullReturnState nullReturn;
+ if (RequiresNullCheck) {
+ nullReturn.init(CGF, Arg0);
+ }
llvm::Instruction *CallSite;
Fn = llvm::ConstantExpr::getBitCast(Fn, MSI.MessengerType);
@@ -2164,7 +2175,7 @@ CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
llvm::CallSite(CallSite).setDoesNotReturn();
}
- return nullReturn.complete(CGF, rvalue, ResultType, CallArgs,
+ return nullReturn.complete(CGF, Return, rvalue, ResultType, CallArgs,
RequiresNullCheck ? Method : nullptr);
}
@@ -6381,16 +6392,15 @@ llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CodeGenFunction &CGF,
llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName);
if (PTGV)
return CGF.Builder.CreateAlignedLoad(PTGV, Align);
- PTGV = new llvm::GlobalVariable(
- CGM.getModule(),
- Init->getType(), false,
- llvm::GlobalValue::WeakAnyLinkage,
- Init,
- ProtocolName);
+ PTGV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
+ llvm::GlobalValue::WeakAnyLinkage, Init,
+ ProtocolName);
PTGV->setSection(GetSectionName("__objc_protorefs",
"coalesced,no_dead_strip"));
PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
PTGV->setAlignment(Align.getQuantity());
+ if (!CGM.getTriple().isOSBinFormatMachO())
+ PTGV->setComdat(CGM.getModule().getOrInsertComdat(ProtocolName));
CGM.addCompilerUsedGlobal(PTGV);
return CGF.Builder.CreateAlignedLoad(PTGV, Align);
}
@@ -7074,7 +7084,7 @@ CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF,
CGCallee callee(CGCalleeInfo(), calleePtr);
RValue result = CGF.EmitCall(MSI.CallInfo, callee, returnSlot, args);
- return nullReturn.complete(CGF, result, resultType, formalArgs,
+ return nullReturn.complete(CGF, returnSlot, result, resultType, formalArgs,
requiresnullCheck ? method : nullptr);
}
diff --git a/lib/CodeGen/CGObjCRuntime.cpp b/lib/CodeGen/CGObjCRuntime.cpp
index b5599dad3096..4cfddcb107cb 100644
--- a/lib/CodeGen/CGObjCRuntime.cpp
+++ b/lib/CodeGen/CGObjCRuntime.cpp
@@ -26,61 +26,27 @@
using namespace clang;
using namespace CodeGen;
-static uint64_t LookupFieldBitOffset(CodeGen::CodeGenModule &CGM,
- const ObjCInterfaceDecl *OID,
- const ObjCImplementationDecl *ID,
- const ObjCIvarDecl *Ivar) {
- const ObjCInterfaceDecl *Container = Ivar->getContainingInterface();
-
- // FIXME: We should eliminate the need to have ObjCImplementationDecl passed
- // in here; it should never be necessary because that should be the lexical
- // decl context for the ivar.
-
- // If we know have an implementation (and the ivar is in it) then
- // look up in the implementation layout.
- const ASTRecordLayout *RL;
- if (ID && declaresSameEntity(ID->getClassInterface(), Container))
- RL = &CGM.getContext().getASTObjCImplementationLayout(ID);
- else
- RL = &CGM.getContext().getASTObjCInterfaceLayout(Container);
-
- // Compute field index.
- //
- // FIXME: The index here is closely tied to how ASTContext::getObjCLayout is
- // implemented. This should be fixed to get the information from the layout
- // directly.
- unsigned Index = 0;
-
- for (const ObjCIvarDecl *IVD = Container->all_declared_ivar_begin();
- IVD; IVD = IVD->getNextIvar()) {
- if (Ivar == IVD)
- break;
- ++Index;
- }
- assert(Index < RL->getFieldCount() && "Ivar is not inside record layout!");
-
- return RL->getFieldOffset(Index);
-}
-
uint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM,
const ObjCInterfaceDecl *OID,
const ObjCIvarDecl *Ivar) {
- return LookupFieldBitOffset(CGM, OID, nullptr, Ivar) /
- CGM.getContext().getCharWidth();
+ return CGM.getContext().lookupFieldBitOffset(OID, nullptr, Ivar) /
+ CGM.getContext().getCharWidth();
}
uint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM,
const ObjCImplementationDecl *OID,
const ObjCIvarDecl *Ivar) {
- return LookupFieldBitOffset(CGM, OID->getClassInterface(), OID, Ivar) /
- CGM.getContext().getCharWidth();
+ return CGM.getContext().lookupFieldBitOffset(OID->getClassInterface(), OID,
+ Ivar) /
+ CGM.getContext().getCharWidth();
}
unsigned CGObjCRuntime::ComputeBitfieldBitOffset(
CodeGen::CodeGenModule &CGM,
const ObjCInterfaceDecl *ID,
const ObjCIvarDecl *Ivar) {
- return LookupFieldBitOffset(CGM, ID, ID->getImplementation(), Ivar);
+ return CGM.getContext().lookupFieldBitOffset(ID, ID->getImplementation(),
+ Ivar);
}
LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF,
@@ -119,7 +85,8 @@ LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF,
// Note, there is a subtle invariant here: we can only call this routine on
// non-synthesized ivars but we may be called for synthesized ivars. However,
// a synthesized ivar can never be a bit-field, so this is safe.
- uint64_t FieldBitOffset = LookupFieldBitOffset(CGF.CGM, OID, nullptr, Ivar);
+ uint64_t FieldBitOffset =
+ CGF.CGM.getContext().lookupFieldBitOffset(OID, nullptr, Ivar);
uint64_t BitOffset = FieldBitOffset % CGF.CGM.getContext().getCharWidth();
uint64_t AlignmentBits = CGF.CGM.getTarget().getCharAlign();
uint64_t BitFieldSize = Ivar->getBitWidthValue(CGF.getContext());
diff --git a/lib/CodeGen/CGOpenMPRuntime.cpp b/lib/CodeGen/CGOpenMPRuntime.cpp
index 8d83255ac139..3df95a4e9b2a 100644
--- a/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -5603,7 +5603,7 @@ public:
// We have to process the component lists that relate with the same
// declaration in a single chunk so that we can generate the map flags
// correctly. Therefore, we organize all lists in a map.
- llvm::DenseMap<const ValueDecl *, SmallVector<MapInfo, 8>> Info;
+ llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info;
// Helper function to fill the information map for the different supported
// clauses.
@@ -5927,16 +5927,11 @@ emitOffloadingArrays(CodeGenFunction &CGF,
for (unsigned i = 0; i < Info.NumberOfPtrs; ++i) {
llvm::Value *BPVal = *BasePointers[i];
- if (BPVal->getType()->isPointerTy())
- BPVal = CGF.Builder.CreateBitCast(BPVal, CGM.VoidPtrTy);
- else {
- assert(BPVal->getType()->isIntegerTy() &&
- "If not a pointer, the value type must be an integer.");
- BPVal = CGF.Builder.CreateIntToPtr(BPVal, CGM.VoidPtrTy);
- }
llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32(
llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
Info.BasePointersArray, 0, i);
+ BP = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ BP, BPVal->getType()->getPointerTo(/*AddrSpace=*/0));
Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
CGF.Builder.CreateStore(BPVal, BPAddr);
@@ -5945,16 +5940,11 @@ emitOffloadingArrays(CodeGenFunction &CGF,
Info.CaptureDeviceAddrMap.insert(std::make_pair(DevVD, BPAddr));
llvm::Value *PVal = Pointers[i];
- if (PVal->getType()->isPointerTy())
- PVal = CGF.Builder.CreateBitCast(PVal, CGM.VoidPtrTy);
- else {
- assert(PVal->getType()->isIntegerTy() &&
- "If not a pointer, the value type must be an integer.");
- PVal = CGF.Builder.CreateIntToPtr(PVal, CGM.VoidPtrTy);
- }
llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32(
llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
Info.PointersArray, 0, i);
+ P = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ P, PVal->getType()->getPointerTo(/*AddrSpace=*/0));
Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
CGF.Builder.CreateStore(PVal, PAddr);
diff --git a/lib/CodeGen/CGStmtOpenMP.cpp b/lib/CodeGen/CGStmtOpenMP.cpp
index 77f3c332a12f..493cd627e418 100644
--- a/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/lib/CodeGen/CGStmtOpenMP.cpp
@@ -239,21 +239,47 @@ static QualType getCanonicalParamType(ASTContext &C, QualType T) {
return C.getCanonicalParamType(T);
}
-llvm::Function *
-CodeGenFunction::GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S) {
- assert(
- CapturedStmtInfo &&
- "CapturedStmtInfo should be set when generating the captured function");
- const CapturedDecl *CD = S.getCapturedDecl();
- const RecordDecl *RD = S.getCapturedRecordDecl();
+namespace {
+ /// Contains required data for proper outlined function codegen.
+ struct FunctionOptions {
+ /// Captured statement for which the function is generated.
+ const CapturedStmt *S = nullptr;
+ /// true if cast to/from UIntPtr is required for variables captured by
+ /// value.
+ bool UIntPtrCastRequired = true;
+ /// true if only casted argumefnts must be registered as local args or VLA
+ /// sizes.
+ bool RegisterCastedArgsOnly = false;
+ /// Name of the generated function.
+ StringRef FunctionName;
+ explicit FunctionOptions(const CapturedStmt *S, bool UIntPtrCastRequired,
+ bool RegisterCastedArgsOnly,
+ StringRef FunctionName)
+ : S(S), UIntPtrCastRequired(UIntPtrCastRequired),
+ RegisterCastedArgsOnly(UIntPtrCastRequired && RegisterCastedArgsOnly),
+ FunctionName(FunctionName) {}
+ };
+}
+
+static std::pair<llvm::Function *, bool> emitOutlinedFunctionPrologue(
+ CodeGenFunction &CGF, FunctionArgList &Args,
+ llvm::DenseMap<const Decl *, std::pair<const VarDecl *, Address>>
+ &LocalAddrs,
+ llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>>
+ &VLASizes,
+ llvm::Value *&CXXThisValue, const FunctionOptions &FO) {
+ const CapturedDecl *CD = FO.S->getCapturedDecl();
+ const RecordDecl *RD = FO.S->getCapturedRecordDecl();
assert(CD->hasBody() && "missing CapturedDecl body");
+ CXXThisValue = nullptr;
// Build the argument list.
+ CodeGenModule &CGM = CGF.CGM;
ASTContext &Ctx = CGM.getContext();
- FunctionArgList Args;
+ bool HasUIntPtrArgs = false;
Args.append(CD->param_begin(),
std::next(CD->param_begin(), CD->getContextParamPosition()));
- auto I = S.captures().begin();
+ auto I = FO.S->captures().begin();
for (auto *FD : RD->fields()) {
QualType ArgType = FD->getType();
IdentifierInfo *II = nullptr;
@@ -265,23 +291,24 @@ CodeGenFunction::GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S) {
// deal with pointers. We can pass in the same way the VLA type sizes to the
// outlined function.
if ((I->capturesVariableByCopy() && !ArgType->isAnyPointerType()) ||
- I->capturesVariableArrayType())
- ArgType = Ctx.getUIntPtrType();
+ I->capturesVariableArrayType()) {
+ HasUIntPtrArgs = true;
+ if (FO.UIntPtrCastRequired)
+ ArgType = Ctx.getUIntPtrType();
+ }
if (I->capturesVariable() || I->capturesVariableByCopy()) {
CapVar = I->getCapturedVar();
II = CapVar->getIdentifier();
} else if (I->capturesThis())
- II = &getContext().Idents.get("this");
+ II = &Ctx.Idents.get("this");
else {
assert(I->capturesVariableArrayType());
- II = &getContext().Idents.get("vla");
+ II = &Ctx.Idents.get("vla");
}
- if (ArgType->isVariablyModifiedType()) {
- ArgType =
- getCanonicalParamType(getContext(), ArgType.getNonReferenceType());
- }
- Args.push_back(ImplicitParamDecl::Create(getContext(), /*DC=*/nullptr,
+ if (ArgType->isVariablyModifiedType())
+ ArgType = getCanonicalParamType(Ctx, ArgType.getNonReferenceType());
+ Args.push_back(ImplicitParamDecl::Create(Ctx, /*DC=*/nullptr,
FD->getLocation(), II, ArgType,
ImplicitParamDecl::Other));
++I;
@@ -296,90 +323,166 @@ CodeGenFunction::GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S) {
CGM.getTypes().arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Args);
llvm::FunctionType *FuncLLVMTy = CGM.getTypes().GetFunctionType(FuncInfo);
- llvm::Function *F = llvm::Function::Create(
- FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
- CapturedStmtInfo->getHelperName(), &CGM.getModule());
+ llvm::Function *F =
+ llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
+ FO.FunctionName, &CGM.getModule());
CGM.SetInternalFunctionAttributes(CD, F, FuncInfo);
if (CD->isNothrow())
F->addFnAttr(llvm::Attribute::NoUnwind);
// Generate the function.
- StartFunction(CD, Ctx.VoidTy, F, FuncInfo, Args, CD->getLocation(),
- CD->getBody()->getLocStart());
+ CGF.StartFunction(CD, Ctx.VoidTy, F, FuncInfo, Args, CD->getLocation(),
+ CD->getBody()->getLocStart());
unsigned Cnt = CD->getContextParamPosition();
- I = S.captures().begin();
+ I = FO.S->captures().begin();
for (auto *FD : RD->fields()) {
// If we are capturing a pointer by copy we don't need to do anything, just
// use the value that we get from the arguments.
if (I->capturesVariableByCopy() && FD->getType()->isAnyPointerType()) {
const VarDecl *CurVD = I->getCapturedVar();
- Address LocalAddr = GetAddrOfLocalVar(Args[Cnt]);
+ Address LocalAddr = CGF.GetAddrOfLocalVar(Args[Cnt]);
// If the variable is a reference we need to materialize it here.
if (CurVD->getType()->isReferenceType()) {
- Address RefAddr = CreateMemTemp(CurVD->getType(), getPointerAlign(),
- ".materialized_ref");
- EmitStoreOfScalar(LocalAddr.getPointer(), RefAddr, /*Volatile=*/false,
- CurVD->getType());
+ Address RefAddr = CGF.CreateMemTemp(
+ CurVD->getType(), CGM.getPointerAlign(), ".materialized_ref");
+ CGF.EmitStoreOfScalar(LocalAddr.getPointer(), RefAddr,
+ /*Volatile=*/false, CurVD->getType());
LocalAddr = RefAddr;
}
- setAddrOfLocalVar(CurVD, LocalAddr);
+ if (!FO.RegisterCastedArgsOnly)
+ LocalAddrs.insert({Args[Cnt], {CurVD, LocalAddr}});
++Cnt;
++I;
continue;
}
LValueBaseInfo BaseInfo(AlignmentSource::Decl, false);
- LValue ArgLVal =
- MakeAddrLValue(GetAddrOfLocalVar(Args[Cnt]), Args[Cnt]->getType(),
- BaseInfo);
+ LValue ArgLVal = CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(Args[Cnt]),
+ Args[Cnt]->getType(), BaseInfo);
if (FD->hasCapturedVLAType()) {
- LValue CastedArgLVal =
- MakeAddrLValue(castValueFromUintptr(*this, FD->getType(),
- Args[Cnt]->getName(), ArgLVal),
- FD->getType(), BaseInfo);
+ if (FO.UIntPtrCastRequired) {
+ ArgLVal = CGF.MakeAddrLValue(castValueFromUintptr(CGF, FD->getType(),
+ Args[Cnt]->getName(),
+ ArgLVal),
+ FD->getType(), BaseInfo);
+ }
auto *ExprArg =
- EmitLoadOfLValue(CastedArgLVal, SourceLocation()).getScalarVal();
+ CGF.EmitLoadOfLValue(ArgLVal, SourceLocation()).getScalarVal();
auto VAT = FD->getCapturedVLAType();
- VLASizeMap[VAT->getSizeExpr()] = ExprArg;
+ VLASizes.insert({Args[Cnt], {VAT->getSizeExpr(), ExprArg}});
} else if (I->capturesVariable()) {
auto *Var = I->getCapturedVar();
QualType VarTy = Var->getType();
Address ArgAddr = ArgLVal.getAddress();
if (!VarTy->isReferenceType()) {
if (ArgLVal.getType()->isLValueReferenceType()) {
- ArgAddr = EmitLoadOfReference(
+ ArgAddr = CGF.EmitLoadOfReference(
ArgAddr, ArgLVal.getType()->castAs<ReferenceType>());
} else if (!VarTy->isVariablyModifiedType() || !VarTy->isPointerType()) {
assert(ArgLVal.getType()->isPointerType());
- ArgAddr = EmitLoadOfPointer(
+ ArgAddr = CGF.EmitLoadOfPointer(
ArgAddr, ArgLVal.getType()->castAs<PointerType>());
}
}
- setAddrOfLocalVar(
- Var, Address(ArgAddr.getPointer(), getContext().getDeclAlign(Var)));
+ if (!FO.RegisterCastedArgsOnly) {
+ LocalAddrs.insert(
+ {Args[Cnt],
+ {Var, Address(ArgAddr.getPointer(), Ctx.getDeclAlign(Var))}});
+ }
} else if (I->capturesVariableByCopy()) {
assert(!FD->getType()->isAnyPointerType() &&
"Not expecting a captured pointer.");
auto *Var = I->getCapturedVar();
QualType VarTy = Var->getType();
- setAddrOfLocalVar(Var, castValueFromUintptr(*this, FD->getType(),
- Args[Cnt]->getName(), ArgLVal,
- VarTy->isReferenceType()));
+ LocalAddrs.insert(
+ {Args[Cnt],
+ {Var,
+ FO.UIntPtrCastRequired
+ ? castValueFromUintptr(CGF, FD->getType(), Args[Cnt]->getName(),
+ ArgLVal, VarTy->isReferenceType())
+ : ArgLVal.getAddress()}});
} else {
// If 'this' is captured, load it into CXXThisValue.
assert(I->capturesThis());
- CXXThisValue =
- EmitLoadOfLValue(ArgLVal, Args[Cnt]->getLocation()).getScalarVal();
+ CXXThisValue = CGF.EmitLoadOfLValue(ArgLVal, Args[Cnt]->getLocation())
+ .getScalarVal();
+ LocalAddrs.insert({Args[Cnt], {nullptr, ArgLVal.getAddress()}});
}
++Cnt;
++I;
}
+ return {F, HasUIntPtrArgs};
+}
+
+llvm::Function *
+CodeGenFunction::GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S) {
+ assert(
+ CapturedStmtInfo &&
+ "CapturedStmtInfo should be set when generating the captured function");
+ const CapturedDecl *CD = S.getCapturedDecl();
+ // Build the argument list.
+ bool NeedWrapperFunction =
+ getDebugInfo() &&
+ CGM.getCodeGenOpts().getDebugInfo() >= codegenoptions::LimitedDebugInfo;
+ FunctionArgList Args;
+ llvm::DenseMap<const Decl *, std::pair<const VarDecl *, Address>> LocalAddrs;
+ llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>> VLASizes;
+ FunctionOptions FO(&S, !NeedWrapperFunction, /*RegisterCastedArgsOnly=*/false,
+ CapturedStmtInfo->getHelperName());
+ llvm::Function *F;
+ bool HasUIntPtrArgs;
+ std::tie(F, HasUIntPtrArgs) = emitOutlinedFunctionPrologue(
+ *this, Args, LocalAddrs, VLASizes, CXXThisValue, FO);
+ for (const auto &LocalAddrPair : LocalAddrs) {
+ if (LocalAddrPair.second.first) {
+ setAddrOfLocalVar(LocalAddrPair.second.first,
+ LocalAddrPair.second.second);
+ }
+ }
+ for (const auto &VLASizePair : VLASizes)
+ VLASizeMap[VLASizePair.second.first] = VLASizePair.second.second;
PGO.assignRegionCounters(GlobalDecl(CD), F);
CapturedStmtInfo->EmitBody(*this, CD->getBody());
FinishFunction(CD->getBodyRBrace());
-
- return F;
+ if (!NeedWrapperFunction || !HasUIntPtrArgs)
+ return F;
+
+ FunctionOptions WrapperFO(&S, /*UIntPtrCastRequired=*/true,
+ /*RegisterCastedArgsOnly=*/true,
+ ".nondebug_wrapper.");
+ CodeGenFunction WrapperCGF(CGM, /*suppressNewContext=*/true);
+ WrapperCGF.disableDebugInfo();
+ Args.clear();
+ LocalAddrs.clear();
+ VLASizes.clear();
+ llvm::Function *WrapperF =
+ emitOutlinedFunctionPrologue(WrapperCGF, Args, LocalAddrs, VLASizes,
+ WrapperCGF.CXXThisValue, WrapperFO).first;
+ LValueBaseInfo BaseInfo(AlignmentSource::Decl, false);
+ llvm::SmallVector<llvm::Value *, 4> CallArgs;
+ for (const auto *Arg : Args) {
+ llvm::Value *CallArg;
+ auto I = LocalAddrs.find(Arg);
+ if (I != LocalAddrs.end()) {
+ LValue LV =
+ WrapperCGF.MakeAddrLValue(I->second.second, Arg->getType(), BaseInfo);
+ CallArg = WrapperCGF.EmitLoadOfScalar(LV, SourceLocation());
+ } else {
+ auto EI = VLASizes.find(Arg);
+ if (EI != VLASizes.end())
+ CallArg = EI->second.second;
+ else {
+ LValue LV = WrapperCGF.MakeAddrLValue(WrapperCGF.GetAddrOfLocalVar(Arg),
+ Arg->getType(), BaseInfo);
+ CallArg = WrapperCGF.EmitLoadOfScalar(LV, SourceLocation());
+ }
+ }
+ CallArgs.emplace_back(CallArg);
+ }
+ WrapperCGF.Builder.CreateCall(F, CallArgs);
+ WrapperCGF.FinishFunction();
+ return WrapperF;
}
//===----------------------------------------------------------------------===//
diff --git a/lib/CodeGen/CodeGenAction.cpp b/lib/CodeGen/CodeGenAction.cpp
index c7e30fad7575..4f03de55149b 100644
--- a/lib/CodeGen/CodeGenAction.cpp
+++ b/lib/CodeGen/CodeGenAction.cpp
@@ -228,7 +228,10 @@ namespace clang {
Ctx.getDiagnosticHandler();
void *OldDiagnosticContext = Ctx.getDiagnosticContext();
Ctx.setDiagnosticHandler(DiagnosticHandler, this);
- Ctx.setDiagnosticHotnessRequested(CodeGenOpts.DiagnosticsWithHotness);
+ Ctx.setDiagnosticsHotnessRequested(CodeGenOpts.DiagnosticsWithHotness);
+ if (CodeGenOpts.DiagnosticsHotnessThreshold != 0)
+ Ctx.setDiagnosticsHotnessThreshold(
+ CodeGenOpts.DiagnosticsHotnessThreshold);
std::unique_ptr<llvm::tool_output_file> OptRecordFile;
if (!CodeGenOpts.OptRecordFile.empty()) {
@@ -246,7 +249,7 @@ namespace clang {
llvm::make_unique<yaml::Output>(OptRecordFile->os()));
if (CodeGenOpts.getProfileUse() != CodeGenOptions::ProfileNone)
- Ctx.setDiagnosticHotnessRequested(true);
+ Ctx.setDiagnosticsHotnessRequested(true);
}
// Link each LinkModule into our module.
diff --git a/lib/CodeGen/CodeGenPGO.cpp b/lib/CodeGen/CodeGenPGO.cpp
index 9e193531d0f6..c3d66c1dabc5 100644
--- a/lib/CodeGen/CodeGenPGO.cpp
+++ b/lib/CodeGen/CodeGenPGO.cpp
@@ -617,6 +617,9 @@ uint64_t PGOHash::finalize() {
void CodeGenPGO::assignRegionCounters(GlobalDecl GD, llvm::Function *Fn) {
const Decl *D = GD.getDecl();
+ if (!D->hasBody())
+ return;
+
bool InstrumentRegions = CGM.getCodeGenOpts().hasProfileClangInstr();
llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader();
if (!InstrumentRegions && !PGOReader)
diff --git a/lib/Driver/Compilation.cpp b/lib/Driver/Compilation.cpp
index 5c13e59a0d73..cf86644fb8cd 100644
--- a/lib/Driver/Compilation.cpp
+++ b/lib/Driver/Compilation.cpp
@@ -23,10 +23,11 @@ using namespace clang;
using namespace llvm::opt;
Compilation::Compilation(const Driver &D, const ToolChain &_DefaultToolChain,
- InputArgList *_Args, DerivedArgList *_TranslatedArgs)
+ InputArgList *_Args, DerivedArgList *_TranslatedArgs,
+ bool ContainsError)
: TheDriver(D), DefaultToolChain(_DefaultToolChain), ActiveOffloadMask(0u),
Args(_Args), TranslatedArgs(_TranslatedArgs), Redirects(nullptr),
- ForDiagnostics(false) {
+ ForDiagnostics(false), ContainsError(ContainsError) {
// The offloading host toolchain is the default tool chain.
OrderedOffloadingToolchains.insert(
std::make_pair(Action::OFK_Host, &DefaultToolChain));
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index f23975829eaf..faced0697ed9 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -153,8 +153,10 @@ void Driver::setDriverModeFromOption(StringRef Opt) {
Diag(diag::err_drv_unsupported_option_argument) << OptName << Value;
}
-InputArgList Driver::ParseArgStrings(ArrayRef<const char *> ArgStrings) {
+InputArgList Driver::ParseArgStrings(ArrayRef<const char *> ArgStrings,
+ bool &ContainsError) {
llvm::PrettyStackTraceString CrashInfo("Command line argument parsing");
+ ContainsError = false;
unsigned IncludedFlagsBitmask;
unsigned ExcludedFlagsBitmask;
@@ -167,27 +169,41 @@ InputArgList Driver::ParseArgStrings(ArrayRef<const char *> ArgStrings) {
IncludedFlagsBitmask, ExcludedFlagsBitmask);
// Check for missing argument error.
- if (MissingArgCount)
- Diag(clang::diag::err_drv_missing_argument)
+ if (MissingArgCount) {
+ Diag(diag::err_drv_missing_argument)
<< Args.getArgString(MissingArgIndex) << MissingArgCount;
+ ContainsError |=
+ Diags.getDiagnosticLevel(diag::err_drv_missing_argument,
+ SourceLocation()) > DiagnosticsEngine::Warning;
+ }
// Check for unsupported options.
for (const Arg *A : Args) {
if (A->getOption().hasFlag(options::Unsupported)) {
- Diag(clang::diag::err_drv_unsupported_opt) << A->getAsString(Args);
+ Diag(diag::err_drv_unsupported_opt) << A->getAsString(Args);
+ ContainsError |= Diags.getDiagnosticLevel(diag::err_drv_unsupported_opt,
+ SourceLocation()) >
+ DiagnosticsEngine::Warning;
continue;
}
// Warn about -mcpu= without an argument.
if (A->getOption().matches(options::OPT_mcpu_EQ) && A->containsValue("")) {
- Diag(clang::diag::warn_drv_empty_joined_argument) << A->getAsString(Args);
+ Diag(diag::warn_drv_empty_joined_argument) << A->getAsString(Args);
+ ContainsError |= Diags.getDiagnosticLevel(
+ diag::warn_drv_empty_joined_argument,
+ SourceLocation()) > DiagnosticsEngine::Warning;
}
}
- for (const Arg *A : Args.filtered(options::OPT_UNKNOWN))
- Diags.Report(IsCLMode() ? diag::warn_drv_unknown_argument_clang_cl :
- diag::err_drv_unknown_argument)
- << A->getAsString(Args);
+ for (const Arg *A : Args.filtered(options::OPT_UNKNOWN)) {
+ auto ID = IsCLMode() ? diag::warn_drv_unknown_argument_clang_cl
+ : diag::err_drv_unknown_argument;
+
+ Diags.Report(ID) << A->getAsString(Args);
+ ContainsError |= Diags.getDiagnosticLevel(ID, SourceLocation()) >
+ DiagnosticsEngine::Warning;
+ }
return Args;
}
@@ -600,9 +616,8 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
// FIXME: This stuff needs to go into the Compilation, not the driver.
bool CCCPrintPhases;
- InputArgList Args = ParseArgStrings(ArgList.slice(1));
- if (Diags.hasErrorOccurred())
- return nullptr;
+ bool ContainsError;
+ InputArgList Args = ParseArgStrings(ArgList.slice(1), ContainsError);
// Silence driver warnings if requested
Diags.setIgnoreAllWarnings(Args.hasArg(options::OPT_w));
@@ -692,7 +707,8 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
*UArgs, computeTargetTriple(*this, DefaultTargetTriple, *UArgs));
// The compilation takes ownership of Args.
- Compilation *C = new Compilation(*this, TC, UArgs.release(), TranslatedArgs);
+ Compilation *C = new Compilation(*this, TC, UArgs.release(), TranslatedArgs,
+ ContainsError);
if (!HandleImmediateArgs(*C))
return C;
diff --git a/lib/Driver/SanitizerArgs.cpp b/lib/Driver/SanitizerArgs.cpp
index 3a30f2a289b0..7a442c83e158 100644
--- a/lib/Driver/SanitizerArgs.cpp
+++ b/lib/Driver/SanitizerArgs.cpp
@@ -32,7 +32,7 @@ enum : SanitizerMask {
RequiresPIE = DataFlow,
NeedsUnwindTables = Address | Thread | Memory | DataFlow,
SupportsCoverage = Address | KernelAddress | Memory | Leak | Undefined |
- Integer | Nullability | DataFlow,
+ Integer | Nullability | DataFlow | Fuzzer,
RecoverableByDefault = Undefined | Integer | Nullability,
Unrecoverable = Unreachable | Return,
LegacyFsanitizeRecoverMask = Undefined | Integer,
diff --git a/lib/Driver/ToolChains/Arch/ARM.cpp b/lib/Driver/ToolChains/Arch/ARM.cpp
index 4eac97620114..8cafd3c74bfb 100644
--- a/lib/Driver/ToolChains/Arch/ARM.cpp
+++ b/lib/Driver/ToolChains/Arch/ARM.cpp
@@ -392,9 +392,7 @@ void arm::getARMTargetFeatures(const ToolChain &TC,
if (B->getOption().matches(options::OPT_mlong_calls))
D.Diag(diag::err_opt_not_valid_with_opt) << A->getAsString(Args) << B->getAsString(Args);
}
-
- CmdArgs.push_back("-backend-option");
- CmdArgs.push_back("-arm-execute-only");
+ Features.push_back("+execute-only");
}
}
}
diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp
index 292cf72b56ca..3731aa83ef06 100644
--- a/lib/Driver/ToolChains/Clang.cpp
+++ b/lib/Driver/ToolChains/Clang.cpp
@@ -35,6 +35,7 @@
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
+#include "llvm/Support/TargetParser.h"
#include "llvm/Support/YAMLParser.h"
#ifdef LLVM_ON_UNIX
@@ -129,6 +130,13 @@ forAllAssociatedToolChains(Compilation &C, const JobAction &JA,
else if (JA.isDeviceOffloading(Action::OFK_Cuda))
Work(*C.getSingleOffloadToolChain<Action::OFK_Host>());
+ if (JA.isHostOffloading(Action::OFK_OpenMP)) {
+ auto TCs = C.getOffloadToolChains<Action::OFK_OpenMP>();
+ for (auto II = TCs.first, IE = TCs.second; II != IE; ++II)
+ Work(*II->second);
+ } else if (JA.isDeviceOffloading(Action::OFK_OpenMP))
+ Work(*C.getSingleOffloadToolChain<Action::OFK_Host>());
+
//
// TODO: Add support for other offloading programming models here.
//
@@ -781,15 +789,14 @@ static void addPGOAndCoverageFlags(Compilation &C, const Driver &D,
CmdArgs.push_back("-femit-coverage-data");
if (Args.hasFlag(options::OPT_fcoverage_mapping,
- options::OPT_fno_coverage_mapping, false) &&
- !ProfileGenerateArg)
- D.Diag(clang::diag::err_drv_argument_only_allowed_with)
- << "-fcoverage-mapping"
- << "-fprofile-instr-generate";
+ options::OPT_fno_coverage_mapping, false)) {
+ if (!ProfileGenerateArg)
+ D.Diag(clang::diag::err_drv_argument_only_allowed_with)
+ << "-fcoverage-mapping"
+ << "-fprofile-instr-generate";
- if (Args.hasFlag(options::OPT_fcoverage_mapping,
- options::OPT_fno_coverage_mapping, false))
CmdArgs.push_back("-fcoverage-mapping");
+ }
if (C.getArgs().hasArg(options::OPT_c) ||
C.getArgs().hasArg(options::OPT_S)) {
@@ -1309,43 +1316,13 @@ void Clang::AddARMTargetArgs(const llvm::Triple &Triple, const ArgList &Args,
// FIXME: Support -meabi.
// FIXME: Parts of this are duplicated in the backend, unify this somehow.
const char *ABIName = nullptr;
- if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
+ if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ))
ABIName = A->getValue();
- } else if (Triple.isOSBinFormatMachO()) {
- if (arm::useAAPCSForMachO(Triple)) {
- ABIName = "aapcs";
- } else if (Triple.isWatchABI()) {
- ABIName = "aapcs16";
- } else {
- ABIName = "apcs-gnu";
- }
- } else if (Triple.isOSWindows()) {
- // FIXME: this is invalid for WindowsCE
- ABIName = "aapcs";
- } else {
- // Select the default based on the platform.
- switch (Triple.getEnvironment()) {
- case llvm::Triple::Android:
- case llvm::Triple::GNUEABI:
- case llvm::Triple::GNUEABIHF:
- case llvm::Triple::MuslEABI:
- case llvm::Triple::MuslEABIHF:
- ABIName = "aapcs-linux";
- break;
- case llvm::Triple::EABIHF:
- case llvm::Triple::EABI:
- ABIName = "aapcs";
- break;
- default:
- if (Triple.getOS() == llvm::Triple::NetBSD)
- ABIName = "apcs-gnu";
- else if (Triple.getOS() == llvm::Triple::OpenBSD)
- ABIName = "aapcs-linux";
- else
- ABIName = "aapcs";
- break;
- }
+ else {
+ std::string CPU = getCPUName(Args, Triple, /*FromAs*/ false);
+ ABIName = llvm::ARM::computeDefaultTargetABI(Triple, CPU).data();
}
+
CmdArgs.push_back("-target-abi");
CmdArgs.push_back(ABIName);
@@ -1993,6 +1970,16 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(NormalizedTriple));
}
+ if (IsOpenMPDevice) {
+ // We have to pass the triple of the host if compiling for an OpenMP device.
+ std::string NormalizedTriple =
+ C.getSingleOffloadToolChain<Action::OFK_Host>()
+ ->getTriple()
+ .normalize();
+ CmdArgs.push_back("-aux-triple");
+ CmdArgs.push_back(Args.MakeArgString(NormalizedTriple));
+ }
+
if (Triple.isOSWindows() && (Triple.getArch() == llvm::Triple::arm ||
Triple.getArch() == llvm::Triple::thumb)) {
unsigned Offset = Triple.getArch() == llvm::Triple::arm ? 4 : 6;
@@ -4056,6 +4043,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_diagnostics_show_hotness, false))
CmdArgs.push_back("-fdiagnostics-show-hotness");
+ if (const Arg *A =
+ Args.getLastArg(options::OPT_fdiagnostics_hotness_threshold_EQ)) {
+ std::string Opt = std::string("-fdiagnostics-hotness-threshold=") + A->getValue();
+ CmdArgs.push_back(Args.MakeArgString(Opt));
+ }
+
if (const Arg *A = Args.getLastArg(options::OPT_fdiagnostics_format_EQ)) {
CmdArgs.push_back("-fdiagnostics-format");
CmdArgs.push_back(A->getValue());
@@ -4140,11 +4133,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_slp_vectorize, EnableSLPVec))
CmdArgs.push_back("-vectorize-slp");
- // -fno-slp-vectorize-aggressive is default.
- if (Args.hasFlag(options::OPT_fslp_vectorize_aggressive,
- options::OPT_fno_slp_vectorize_aggressive, false))
- CmdArgs.push_back("-vectorize-slp-aggressive");
-
if (Arg *A = Args.getLastArg(options::OPT_fshow_overloads_EQ))
A->render(Args, CmdArgs);
@@ -4413,10 +4401,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// device declarations can be identified. Also, -fopenmp-is-device is passed
// along to tell the frontend that it is generating code for a device, so that
// only the relevant declarations are emitted.
- if (IsOpenMPDevice && Inputs.size() == 2) {
+ if (IsOpenMPDevice) {
CmdArgs.push_back("-fopenmp-is-device");
- CmdArgs.push_back("-fopenmp-host-ir-file-path");
- CmdArgs.push_back(Args.MakeArgString(Inputs.back().getFilename()));
+ if (Inputs.size() == 2) {
+ CmdArgs.push_back("-fopenmp-host-ir-file-path");
+ CmdArgs.push_back(Args.MakeArgString(Inputs.back().getFilename()));
+ }
}
// For all the host OpenMP offloading compile jobs we need to pass the targets
diff --git a/lib/Driver/ToolChains/CommonArgs.cpp b/lib/Driver/ToolChains/CommonArgs.cpp
index 5e360f62e21a..e8bb703054de 100644
--- a/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/lib/Driver/ToolChains/CommonArgs.cpp
@@ -215,6 +215,21 @@ static std::string getR600TargetGPU(const ArgList &Args) {
return "";
}
+static std::string getNios2TargetCPU(const ArgList &Args) {
+ Arg *A = Args.getLastArg(options::OPT_mcpu_EQ);
+ if (!A)
+ A = Args.getLastArg(options::OPT_march_EQ);
+
+ if (!A)
+ return "";
+
+ const char *name = A->getValue();
+ return llvm::StringSwitch<const char *>(name)
+ .Case("r1", "nios2r1")
+ .Case("r2", "nios2r2")
+ .Default(name);
+}
+
static std::string getLanaiTargetCPU(const ArgList &Args) {
if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
return A->getValue();
@@ -267,6 +282,10 @@ std::string tools::getCPUName(const ArgList &Args, const llvm::Triple &T,
return A->getValue();
return "";
+ case llvm::Triple::nios2: {
+ return getNios2TargetCPU(Args);
+ }
+
case llvm::Triple::mips:
case llvm::Triple::mipsel:
case llvm::Triple::mips64:
@@ -598,7 +617,8 @@ bool tools::addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
NonWholeStaticRuntimes, HelperStaticRuntimes,
RequiredSymbols);
// Inject libfuzzer dependencies.
- if (TC.getSanitizerArgs().needsFuzzer()) {
+ if (TC.getSanitizerArgs().needsFuzzer()
+ && !Args.hasArg(options::OPT_shared)) {
addLibFuzzerRuntime(TC, Args, CmdArgs);
}
diff --git a/lib/Driver/ToolChains/CrossWindows.cpp b/lib/Driver/ToolChains/CrossWindows.cpp
index d290c62a056a..7d0c438b1360 100644
--- a/lib/Driver/ToolChains/CrossWindows.cpp
+++ b/lib/Driver/ToolChains/CrossWindows.cpp
@@ -238,8 +238,15 @@ AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
const Driver &D = getDriver();
const std::string &SysRoot = D.SysRoot;
- if (DriverArgs.hasArg(options::OPT_nostdlibinc))
+ auto AddSystemAfterIncludes = [&]() {
+ for (const auto &P : DriverArgs.getAllArgValues(options::OPT_isystem_after))
+ addSystemInclude(DriverArgs, CC1Args, P);
+ };
+
+ if (DriverArgs.hasArg(options::OPT_nostdinc)) {
+ AddSystemAfterIncludes();
return;
+ }
addSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/local/include");
if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
@@ -247,8 +254,7 @@ AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::sys::path::append(ResourceDir, "include");
addSystemInclude(DriverArgs, CC1Args, ResourceDir);
}
- for (const auto &P : DriverArgs.getAllArgValues(options::OPT_isystem_after))
- addSystemInclude(DriverArgs, CC1Args, P);
+ AddSystemAfterIncludes();
addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include");
}
@@ -258,7 +264,7 @@ AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
const llvm::Triple &Triple = getTriple();
const std::string &SysRoot = getDriver().SysRoot;
- if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
+ if (DriverArgs.hasArg(options::OPT_nostdinc) ||
DriverArgs.hasArg(options::OPT_nostdincxx))
return;
diff --git a/lib/Driver/ToolChains/Darwin.cpp b/lib/Driver/ToolChains/Darwin.cpp
index e41b50c40b28..7b61095c3ba9 100644
--- a/lib/Driver/ToolChains/Darwin.cpp
+++ b/lib/Driver/ToolChains/Darwin.cpp
@@ -1053,7 +1053,7 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
AddLinkSanitizerLibArgs(Args, CmdArgs, "ubsan");
if (Sanitize.needsTsanRt())
AddLinkSanitizerLibArgs(Args, CmdArgs, "tsan");
- if (Sanitize.needsFuzzer())
+ if (Sanitize.needsFuzzer() && !Args.hasArg(options::OPT_dynamiclib))
AddFuzzerLinkArgs(Args, CmdArgs);
if (Sanitize.needsStatsRt()) {
StringRef OS = isTargetMacOS() ? "osx" : "iossim";
@@ -1150,6 +1150,17 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
Args.getLastArg(options::OPT_mwatchos_version_min_EQ,
options::OPT_mwatchos_simulator_version_min_EQ);
+ unsigned Major, Minor, Micro;
+ bool HadExtra;
+
+ // iOS 10 is the maximum deployment target for 32-bit targets.
+ if (iOSVersion && getTriple().isArch32Bit() &&
+ Driver::GetReleaseVersion(iOSVersion->getValue(), Major, Minor, Micro,
+ HadExtra) &&
+ Major > 10)
+ getDriver().Diag(diag::err_invalid_ios_deployment_target)
+ << iOSVersion->getAsString(Args);
+
// Add a macro to differentiate between m(iphone|tv|watch)os-version-min=X.Y and
// -m(iphone|tv|watch)simulator-version-min=X.Y.
if (Args.hasArg(options::OPT_mios_simulator_version_min_EQ) ||
@@ -1191,6 +1202,14 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
if (char *env = ::getenv("WATCHOS_DEPLOYMENT_TARGET"))
WatchOSTarget = env;
+ // iOS 10 is the maximum deployment target for 32-bit targets.
+ if (!iOSTarget.empty() && getTriple().isArch32Bit() &&
+ Driver::GetReleaseVersion(iOSTarget.c_str(), Major, Minor, Micro,
+ HadExtra) &&
+ Major > 10)
+ getDriver().Diag(diag::err_invalid_ios_deployment_target)
+ << std::string("IPHONEOS_DEPLOYMENT_TARGET=") + iOSTarget;
+
// If there is no command-line argument to specify the Target version and
// no environment variable defined, see if we can set the default based
// on -isysroot.
@@ -1308,8 +1327,6 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
llvm_unreachable("Unable to infer Darwin variant");
// Set the tool chain target information.
- unsigned Major, Minor, Micro;
- bool HadExtra;
if (Platform == MacOS) {
assert((!iOSVersion && !TvOSVersion && !WatchOSVersion) &&
"Unknown target platform!");
@@ -1325,6 +1342,13 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
HadExtra || Major >= 100 || Minor >= 100 || Micro >= 100)
getDriver().Diag(diag::err_drv_invalid_version_number)
<< iOSVersion->getAsString(Args);
+ // iOS 10 is the maximum deployment target for 32-bit targets. If the
+ // inferred deployment target is iOS 11 or later, set it to 10.99.
+ if (getTriple().isArch32Bit() && Major >= 11) {
+ Major = 10;
+ Minor = 99;
+ Micro = 99;
+ }
} else if (Platform == TvOS) {
if (!Driver::GetReleaseVersion(TvOSVersion->getValue(), Major, Minor,
Micro, HadExtra) || HadExtra ||
@@ -1667,6 +1691,28 @@ void MachO::AddLinkRuntimeLibArgs(const ArgList &Args,
AddLinkRuntimeLib(Args, CmdArgs, CompilerRT, false, true);
}
+bool Darwin::isAlignedAllocationUnavailable() const {
+ switch (TargetPlatform) {
+ case MacOS: // Earlier than 10.13.
+ return TargetVersion < VersionTuple(10U, 13U, 0U);
+ case IPhoneOS:
+ case IPhoneOSSimulator:
+ case TvOS:
+ case TvOSSimulator: // Earlier than 11.0.
+ return TargetVersion < VersionTuple(11U, 0U, 0U);
+ case WatchOS:
+ case WatchOSSimulator: // Earlier than 4.0.
+ return TargetVersion < VersionTuple(4U, 0U, 0U);
+ }
+ llvm_unreachable("Unsupported platform");
+}
+
+void Darwin::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const {
+ if (isAlignedAllocationUnavailable())
+ CC1Args.push_back("-faligned-alloc-unavailable");
+}
+
DerivedArgList *
Darwin::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch,
Action::OffloadKind DeviceOffloadKind) const {
diff --git a/lib/Driver/ToolChains/Darwin.h b/lib/Driver/ToolChains/Darwin.h
index 16ed04286ac0..ffcdf9a71a46 100644
--- a/lib/Driver/ToolChains/Darwin.h
+++ b/lib/Driver/ToolChains/Darwin.h
@@ -384,6 +384,14 @@ protected:
return TargetVersion < VersionTuple(V0, V1, V2);
}
+ /// Return true if c++17 aligned allocation/deallocation functions are not
+ /// implemented in the c++ standard library of the deployment target we are
+ /// targeting.
+ bool isAlignedAllocationUnavailable() const;
+
+ void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+
StringRef getPlatformFamily() const;
static StringRef getSDKName(StringRef isysroot);
StringRef getOSLibraryNameSuffix() const;
diff --git a/lib/Driver/ToolChains/MipsLinux.cpp b/lib/Driver/ToolChains/MipsLinux.cpp
index 709c396a64b7..b394208336ed 100644
--- a/lib/Driver/ToolChains/MipsLinux.cpp
+++ b/lib/Driver/ToolChains/MipsLinux.cpp
@@ -109,7 +109,7 @@ std::string MipsLLVMToolChain::findLibCxxIncludePath() const {
void MipsLLVMToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
assert((GetCXXStdlibType(Args) == ToolChain::CST_Libcxx) &&
- "Only -lc++ (aka libxx) is suported in this toolchain.");
+ "Only -lc++ (aka libxx) is supported in this toolchain.");
CmdArgs.push_back("-lc++");
CmdArgs.push_back("-lc++abi");
diff --git a/lib/Format/ContinuationIndenter.cpp b/lib/Format/ContinuationIndenter.cpp
index cca773cfe3cb..4197587a74c0 100644
--- a/lib/Format/ContinuationIndenter.cpp
+++ b/lib/Format/ContinuationIndenter.cpp
@@ -56,6 +56,8 @@ static bool startsNextParameter(const FormatToken &Current,
if (Current.is(TT_CtorInitializerComma) &&
Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeComma)
return true;
+ if (Style.Language == FormatStyle::LK_Proto && Current.is(TT_SelectorName))
+ return true;
return Previous.is(tok::comma) && !Current.isTrailingComment() &&
((Previous.isNot(TT_CtorInitializerComma) ||
Style.BreakConstructorInitializers !=
@@ -499,6 +501,13 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,
}
}
+static bool lessOpensProtoMessageField(const FormatToken &LessTok,
+ const LineState &State) {
+ assert(LessTok.is(tok::less));
+ return LessTok.NestingLevel > 0 ||
+ (LessTok.Previous && LessTok.Previous->is(tok::equal));
+}
+
unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State,
bool DryRun) {
FormatToken &Current = *State.NextToken;
@@ -641,6 +650,9 @@ unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State,
// before the corresponding } or ].
if (PreviousNonComment &&
(PreviousNonComment->isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) ||
+ (Style.Language == FormatStyle::LK_Proto &&
+ PreviousNonComment->is(tok::less) &&
+ lessOpensProtoMessageField(*PreviousNonComment, State)) ||
(PreviousNonComment->is(TT_TemplateString) &&
PreviousNonComment->opensScope())))
State.Stack.back().BreakBeforeClosingBrace = true;
@@ -682,7 +694,9 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
if (NextNonComment->is(tok::l_brace) && NextNonComment->BlockKind == BK_Block)
return Current.NestingLevel == 0 ? State.FirstIndent
: State.Stack.back().Indent;
- if (Current.isOneOf(tok::r_brace, tok::r_square) && State.Stack.size() > 1) {
+ if ((Current.isOneOf(tok::r_brace, tok::r_square) ||
+ (Current.is(tok::greater) && Style.Language == FormatStyle::LK_Proto)) &&
+ State.Stack.size() > 1) {
if (Current.closesBlockOrBlockTypeList(Style))
return State.Stack[State.Stack.size() - 2].NestedBlockIndent;
if (Current.MatchingParen &&
@@ -1035,7 +1049,9 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
bool BreakBeforeParameter = false;
unsigned NestedBlockIndent = std::max(State.Stack.back().StartOfFunctionCall,
State.Stack.back().NestedBlockIndent);
- if (Current.isOneOf(tok::l_brace, TT_ArrayInitializerLSquare)) {
+ if (Current.isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) ||
+ (Style.Language == FormatStyle::LK_Proto && Current.is(tok::less) &&
+ lessOpensProtoMessageField(Current, State))) {
if (Current.opensBlockOrBlockTypeList(Style)) {
NewIndent = Style.IndentWidth +
std::min(State.Column, State.Stack.back().NestedBlockIndent);
@@ -1047,12 +1063,12 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
Current.MatchingParen->Previous &&
Current.MatchingParen->Previous->is(tok::comma);
AvoidBinPacking =
- (Current.is(TT_ArrayInitializerLSquare) && EndsInComma) ||
- Current.is(TT_DictLiteral) ||
+ EndsInComma || Current.is(TT_DictLiteral) ||
Style.Language == FormatStyle::LK_Proto || !Style.BinPackArguments ||
(NextNoComment &&
NextNoComment->isOneOf(TT_DesignatedInitializerPeriod,
TT_DesignatedInitializerLSquare));
+ BreakBeforeParameter = EndsInComma;
if (Current.ParameterCount > 1)
NestedBlockIndent = std::max(NestedBlockIndent, State.Column + 1);
} else {
diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp
index 7659d56adf25..bb6781d79517 100644
--- a/lib/Format/Format.cpp
+++ b/lib/Format/Format.cpp
@@ -44,7 +44,6 @@
using clang::format::FormatStyle;
-LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(std::string)
LLVM_YAML_IS_SEQUENCE_VECTOR(clang::format::FormatStyle::IncludeCategory)
namespace llvm {
@@ -414,7 +413,9 @@ template <> struct MappingTraits<FormatStyle::BraceWrappingFlags> {
IO.mapOptional("BeforeCatch", Wrapping.BeforeCatch);
IO.mapOptional("BeforeElse", Wrapping.BeforeElse);
IO.mapOptional("IndentBraces", Wrapping.IndentBraces);
- IO.mapOptional("SplitEmptyFunctionBody", Wrapping.SplitEmptyFunctionBody);
+ IO.mapOptional("SplitEmptyFunction", Wrapping.SplitEmptyFunction);
+ IO.mapOptional("SplitEmptyRecord", Wrapping.SplitEmptyRecord);
+ IO.mapOptional("SplitEmptyNamespace", Wrapping.SplitEmptyNamespace);
}
};
@@ -490,7 +491,8 @@ static FormatStyle expandPresets(const FormatStyle &Style) {
return Style;
FormatStyle Expanded = Style;
Expanded.BraceWrapping = {false, false, false, false, false, false,
- false, false, false, false, false, true};
+ false, false, false, false, false, true,
+ true, true};
switch (Style.BreakBeforeBraces) {
case FormatStyle::BS_Linux:
Expanded.BraceWrapping.AfterClass = true;
@@ -503,7 +505,8 @@ static FormatStyle expandPresets(const FormatStyle &Style) {
Expanded.BraceWrapping.AfterFunction = true;
Expanded.BraceWrapping.AfterStruct = true;
Expanded.BraceWrapping.AfterUnion = true;
- Expanded.BraceWrapping.SplitEmptyFunctionBody = false;
+ Expanded.BraceWrapping.SplitEmptyFunction = false;
+ Expanded.BraceWrapping.SplitEmptyRecord = false;
break;
case FormatStyle::BS_Stroustrup:
Expanded.BraceWrapping.AfterFunction = true;
@@ -523,7 +526,8 @@ static FormatStyle expandPresets(const FormatStyle &Style) {
break;
case FormatStyle::BS_GNU:
Expanded.BraceWrapping = {true, true, true, true, true, true,
- true, true, true, true, true, true};
+ true, true, true, true, true, true,
+ true, true};
break;
case FormatStyle::BS_WebKit:
Expanded.BraceWrapping.AfterFunction = true;
@@ -560,7 +564,8 @@ FormatStyle getLLVMStyle() {
LLVMStyle.BreakBeforeTernaryOperators = true;
LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach;
LLVMStyle.BraceWrapping = {false, false, false, false, false, false,
- false, false, false, false, false, true};
+ false, false, false, false, false, true,
+ true, true};
LLVMStyle.BreakAfterJavaFieldAnnotations = false;
LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon;
LLVMStyle.BreakBeforeInheritanceComma = false;
@@ -579,9 +584,9 @@ FormatStyle getLLVMStyle() {
LLVMStyle.ForEachMacros.push_back("Q_FOREACH");
LLVMStyle.ForEachMacros.push_back("BOOST_FOREACH");
LLVMStyle.IncludeCategories = {{"^\"(llvm|llvm-c|clang|clang-c)/", 2},
- {"^(<|\"(gtest|isl|json)/)", 3},
+ {"^(<|\"(gtest|gmock|isl|json)/)", 3},
{".*", 1}};
- LLVMStyle.IncludeIsMainRegex = "$";
+ LLVMStyle.IncludeIsMainRegex = "(Test)?$";
LLVMStyle.IndentCaseLabels = false;
LLVMStyle.IndentWrappedFunctionNames = false;
LLVMStyle.IndentWidth = 2;
@@ -1409,7 +1414,7 @@ public:
: Style(Style), FileName(FileName) {
FileStem = llvm::sys::path::stem(FileName);
for (const auto &Category : Style.IncludeCategories)
- CategoryRegexs.emplace_back(Category.Regex);
+ CategoryRegexs.emplace_back(Category.Regex, llvm::Regex::IgnoreCase);
IsMainFile = FileName.endswith(".c") || FileName.endswith(".cc") ||
FileName.endswith(".cpp") || FileName.endswith(".c++") ||
FileName.endswith(".cxx") || FileName.endswith(".m") ||
@@ -1437,9 +1442,11 @@ private:
return false;
StringRef HeaderStem =
llvm::sys::path::stem(IncludeName.drop_front(1).drop_back(1));
- if (FileStem.startswith(HeaderStem)) {
+ if (FileStem.startswith(HeaderStem) ||
+ FileStem.startswith_lower(HeaderStem)) {
llvm::Regex MainIncludeRegex(
- (HeaderStem + Style.IncludeIsMainRegex).str());
+ (HeaderStem + Style.IncludeIsMainRegex).str(),
+ llvm::Regex::IgnoreCase);
if (MainIncludeRegex.match(FileStem))
return true;
}
diff --git a/lib/Format/FormatToken.h b/lib/Format/FormatToken.h
index c5bf48cdcc06..0fe91adcd472 100644
--- a/lib/Format/FormatToken.h
+++ b/lib/Format/FormatToken.h
@@ -465,7 +465,8 @@ struct FormatToken {
return is(TT_ArrayInitializerLSquare) ||
(is(tok::l_brace) &&
(BlockKind == BK_Block || is(TT_DictLiteral) ||
- (!Style.Cpp11BracedListStyle && NestingLevel == 0)));
+ (!Style.Cpp11BracedListStyle && NestingLevel == 0))) ||
+ (is(tok::less) && Style.Language == FormatStyle::LK_Proto);
}
/// \brief Same as opensBlockOrBlockTypeList, but for the closing token.
@@ -475,6 +476,19 @@ struct FormatToken {
return MatchingParen && MatchingParen->opensBlockOrBlockTypeList(Style);
}
+ /// \brief Return the actual namespace token, if this token starts a namespace
+ /// block.
+ const FormatToken *getNamespaceToken() const {
+ const FormatToken *NamespaceTok = this;
+ if (is(tok::comment))
+ NamespaceTok = NamespaceTok->getNextNonComment();
+ // Detect "(inline)? namespace" in the beginning of a line.
+ if (NamespaceTok && NamespaceTok->is(tok::kw_inline))
+ NamespaceTok = NamespaceTok->getNextNonComment();
+ return NamespaceTok && NamespaceTok->is(tok::kw_namespace) ? NamespaceTok
+ : nullptr;
+ }
+
private:
// Disallow copying.
FormatToken(const FormatToken &) = delete;
diff --git a/lib/Format/NamespaceEndCommentsFixer.cpp b/lib/Format/NamespaceEndCommentsFixer.cpp
index 1bbb41f757ae..85b70b8c0a76 100644
--- a/lib/Format/NamespaceEndCommentsFixer.cpp
+++ b/lib/Format/NamespaceEndCommentsFixer.cpp
@@ -174,7 +174,7 @@ tooling::Replacements NamespaceEndCommentsFixer::analyze(
AllNamespaceNames = "::" + NamespaceName + AllNamespaceNames;
continue;
}
- NamespaceName += std::move(AllNamespaceNames);
+ NamespaceName += AllNamespaceNames;
CompactedNamespacesCount = 0;
AllNamespaceNames = std::string();
}
diff --git a/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp
index 505f42ec9a06..d78a37532fe8 100644
--- a/lib/Format/TokenAnnotator.cpp
+++ b/lib/Format/TokenAnnotator.cpp
@@ -89,7 +89,8 @@ private:
continue;
}
if (CurrentToken->isOneOf(tok::r_paren, tok::r_square, tok::r_brace) ||
- (CurrentToken->isOneOf(tok::colon, tok::question) && InExprContext))
+ (CurrentToken->isOneOf(tok::colon, tok::question) && InExprContext &&
+ Style.Language != FormatStyle::LK_Proto))
return false;
// If a && or || is found and interpreted as a binary operator, this set
// of angles is likely part of something like "a < b && c > d". If the
@@ -103,6 +104,14 @@ private:
!Line.startsWith(tok::kw_template))
return false;
updateParameterCount(Left, CurrentToken);
+ if (Style.Language == FormatStyle::LK_Proto) {
+ if (FormatToken *Previous = CurrentToken->getPreviousNonComment()) {
+ if (CurrentToken->is(tok::colon) ||
+ (CurrentToken->isOneOf(tok::l_brace, tok::less) &&
+ Previous->isNot(tok::colon)))
+ Previous->Type = TT_SelectorName;
+ }
+ }
if (!consumeToken())
return false;
}
@@ -440,7 +449,7 @@ private:
if (CurrentToken->isOneOf(tok::r_paren, tok::r_square))
return false;
updateParameterCount(Left, CurrentToken);
- if (CurrentToken->isOneOf(tok::colon, tok::l_brace)) {
+ if (CurrentToken->isOneOf(tok::colon, tok::l_brace, tok::less)) {
FormatToken *Previous = CurrentToken->getPreviousNonComment();
if (((CurrentToken->is(tok::colon) &&
(!Contexts.back().ColonIsDictLiteral || !Style.isCpp())) ||
@@ -1561,8 +1570,10 @@ private:
const FormatToken *NextNonComment = Current->getNextNonComment();
if (Current->is(TT_ConditionalExpr))
return prec::Conditional;
- if (NextNonComment && NextNonComment->is(tok::colon) &&
- NextNonComment->is(TT_DictLiteral))
+ if (NextNonComment && Current->is(TT_SelectorName) &&
+ (NextNonComment->is(TT_DictLiteral) ||
+ (Style.Language == FormatStyle::LK_Proto &&
+ NextNonComment->is(tok::less))))
return prec::Assignment;
if (Current->is(TT_JsComputedPropertyName))
return prec::Assignment;
@@ -2549,10 +2560,16 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
// deliberate choice and might have aligned the contents of the string
// literal accordingly. Thus, we try keep existing line breaks.
return Right.NewlinesBefore > 0;
- if (Right.Previous->is(tok::l_brace) && Right.NestingLevel == 1 &&
- Style.Language == FormatStyle::LK_Proto)
- // Don't put enums onto single lines in protocol buffers.
+ if ((Right.Previous->is(tok::l_brace) ||
+ (Right.Previous->is(tok::less) &&
+ Right.Previous->Previous &&
+ Right.Previous->Previous->is(tok::equal))
+ ) &&
+ Right.NestingLevel == 1 && Style.Language == FormatStyle::LK_Proto) {
+ // Don't put enums or option definitions onto single lines in protocol
+ // buffers.
return true;
+ }
if (Right.is(TT_InlineASMBrace))
return Right.HasUnescapedNewline;
if (isAllmanBrace(Left) || isAllmanBrace(Right))
diff --git a/lib/Format/UnwrappedLineFormatter.cpp b/lib/Format/UnwrappedLineFormatter.cpp
index 8836c07cac71..2005a2822924 100644
--- a/lib/Format/UnwrappedLineFormatter.cpp
+++ b/lib/Format/UnwrappedLineFormatter.cpp
@@ -136,10 +136,7 @@ private:
bool isNamespaceDeclaration(const AnnotatedLine *Line) {
const FormatToken *NamespaceTok = Line->First;
- // Detect "(inline)? namespace" in the beginning of a line.
- if (NamespaceTok->is(tok::kw_inline))
- NamespaceTok = NamespaceTok->getNextNonComment();
- return NamespaceTok && NamespaceTok->is(tok::kw_namespace);
+ return NamespaceTok && NamespaceTok->getNamespaceToken();
}
bool isEndOfNamespace(const AnnotatedLine *Line,
@@ -216,10 +213,31 @@ private:
if (TheLine->Last->is(TT_FunctionLBrace) &&
TheLine->First == TheLine->Last &&
- !Style.BraceWrapping.SplitEmptyFunctionBody &&
+ !Style.BraceWrapping.SplitEmptyFunction &&
I[1]->First->is(tok::r_brace))
return tryMergeSimpleBlock(I, E, Limit);
+ // Handle empty record blocks where the brace has already been wrapped
+ if (TheLine->Last->is(tok::l_brace) && TheLine->First == TheLine->Last &&
+ I != AnnotatedLines.begin()) {
+ bool EmptyBlock = I[1]->First->is(tok::r_brace);
+
+ const FormatToken *Tok = I[-1]->First;
+ if (Tok && Tok->is(tok::comment))
+ Tok = Tok->getNextNonComment();
+
+ if (Tok && Tok->getNamespaceToken())
+ return !Style.BraceWrapping.SplitEmptyNamespace && EmptyBlock
+ ? tryMergeSimpleBlock(I, E, Limit) : 0;
+
+ if (Tok && Tok->is(tok::kw_typedef))
+ Tok = Tok->getNextNonComment();
+ if (Tok && Tok->isOneOf(tok::kw_class, tok::kw_struct, tok::kw_union,
+ Keywords.kw_interface))
+ return !Style.BraceWrapping.SplitEmptyRecord && EmptyBlock
+ ? tryMergeSimpleBlock(I, E, Limit) : 0;
+ }
+
// FIXME: TheLine->Level != 0 might or might not be the right check to do.
// If necessary, change to something smarter.
bool MergeShortFunctions =
diff --git a/lib/Format/UnwrappedLineParser.cpp b/lib/Format/UnwrappedLineParser.cpp
index f7678bb6b2a5..ba3a4c17ee12 100644
--- a/lib/Format/UnwrappedLineParser.cpp
+++ b/lib/Format/UnwrappedLineParser.cpp
@@ -1176,9 +1176,12 @@ void UnwrappedLineParser::parseStructuralElement() {
}
nextToken();
- if (FormatTok->Tok.is(tok::l_brace)) {
+ if (FormatTok->Tok.is(tok::l_brace))
parseBracedList();
- }
+ else if (Style.Language == FormatStyle::LK_Proto &&
+ FormatTok->Tok.is(tok::less))
+ parseBracedList(/*ContinueOnSemicolons=*/false,
+ /*ClosingBraceKind=*/tok::greater);
break;
case tok::l_square:
parseSquare();
@@ -1346,7 +1349,8 @@ bool UnwrappedLineParser::tryToParseBracedList() {
return true;
}
-bool UnwrappedLineParser::parseBracedList(bool ContinueOnSemicolons) {
+bool UnwrappedLineParser::parseBracedList(bool ContinueOnSemicolons,
+ tok::TokenKind ClosingBraceKind) {
bool HasError = false;
nextToken();
@@ -1375,6 +1379,10 @@ bool UnwrappedLineParser::parseBracedList(bool ContinueOnSemicolons) {
parseChildBlock();
}
}
+ if (FormatTok->Tok.getKind() == ClosingBraceKind) {
+ nextToken();
+ return !HasError;
+ }
switch (FormatTok->Tok.getKind()) {
case tok::caret:
nextToken();
@@ -1401,9 +1409,6 @@ bool UnwrappedLineParser::parseBracedList(bool ContinueOnSemicolons) {
FormatTok->BlockKind = BK_BracedInit;
parseBracedList();
break;
- case tok::r_brace:
- nextToken();
- return !HasError;
case tok::semi:
// JavaScript (or more precisely TypeScript) can have semicolons in braced
// lists (in so-called TypeMemberLists). Thus, the semicolon cannot be
diff --git a/lib/Format/UnwrappedLineParser.h b/lib/Format/UnwrappedLineParser.h
index 15d1d9cda7a2..a2aa2f006728 100644
--- a/lib/Format/UnwrappedLineParser.h
+++ b/lib/Format/UnwrappedLineParser.h
@@ -93,7 +93,8 @@ private:
void readTokenWithJavaScriptASI();
void parseStructuralElement();
bool tryToParseBracedList();
- bool parseBracedList(bool ContinueOnSemicolons = false);
+ bool parseBracedList(bool ContinueOnSemicolons = false,
+ tok::TokenKind ClosingBraceKind = tok::r_brace);
void parseParens();
void parseSquare();
void parseIfThenElse();
diff --git a/lib/Frontend/ASTMerge.cpp b/lib/Frontend/ASTMerge.cpp
index 986f98ae598b..354527db7bad 100644
--- a/lib/Frontend/ASTMerge.cpp
+++ b/lib/Frontend/ASTMerge.cpp
@@ -44,9 +44,9 @@ void ASTMergeAction::ExecuteAction() {
new ForwardingDiagnosticConsumer(
*CI.getDiagnostics().getClient()),
/*ShouldOwnClient=*/true));
- std::unique_ptr<ASTUnit> Unit =
- ASTUnit::LoadFromASTFile(ASTFiles[I], CI.getPCHContainerReader(),
- Diags, CI.getFileSystemOpts(), false);
+ std::unique_ptr<ASTUnit> Unit = ASTUnit::LoadFromASTFile(
+ ASTFiles[I], CI.getPCHContainerReader(), ASTUnit::LoadEverything, Diags,
+ CI.getFileSystemOpts(), false);
if (!Unit)
continue;
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
index 1f34f10f55af..1094e6d089a6 100644
--- a/lib/Frontend/ASTUnit.cpp
+++ b/lib/Frontend/ASTUnit.cpp
@@ -458,7 +458,7 @@ namespace {
/// a Preprocessor.
class ASTInfoCollector : public ASTReaderListener {
Preprocessor &PP;
- ASTContext &Context;
+ ASTContext *Context;
HeaderSearchOptions &HSOpts;
PreprocessorOptions &PPOpts;
LangOptions &LangOpt;
@@ -468,7 +468,7 @@ class ASTInfoCollector : public ASTReaderListener {
bool InitializedLanguage;
public:
- ASTInfoCollector(Preprocessor &PP, ASTContext &Context,
+ ASTInfoCollector(Preprocessor &PP, ASTContext *Context,
HeaderSearchOptions &HSOpts, PreprocessorOptions &PPOpts,
LangOptions &LangOpt,
std::shared_ptr<TargetOptions> &TargetOpts,
@@ -536,12 +536,15 @@ private:
// Initialize the preprocessor.
PP.Initialize(*Target);
+ if (!Context)
+ return;
+
// Initialize the ASTContext
- Context.InitBuiltinTypes(*Target);
+ Context->InitBuiltinTypes(*Target);
// We didn't have access to the comment options when the ASTContext was
// constructed, so register them now.
- Context.getCommentCommandTraits().registerCommentOptions(
+ Context->getCommentCommandTraits().registerCommentOptions(
LangOpt.CommentOpts);
}
};
@@ -671,7 +674,7 @@ void ASTUnit::ConfigureDiags(IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile(
const std::string &Filename, const PCHContainerReader &PCHContainerRdr,
- IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
+ WhatToLoad ToLoad, IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
const FileSystemOptions &FileSystemOpts, bool UseDebugInfo,
bool OnlyLocalDecls, ArrayRef<RemappedFile> RemappedFiles,
bool CaptureDiagnostics, bool AllowPCHWithCompilerErrors,
@@ -722,21 +725,21 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile(
/*OwnsHeaderSearch=*/false);
Preprocessor &PP = *AST->PP;
- AST->Ctx = new ASTContext(*AST->LangOpts, AST->getSourceManager(),
- PP.getIdentifierTable(), PP.getSelectorTable(),
- PP.getBuiltinInfo());
- ASTContext &Context = *AST->Ctx;
+ if (ToLoad >= LoadASTOnly)
+ AST->Ctx = new ASTContext(*AST->LangOpts, AST->getSourceManager(),
+ PP.getIdentifierTable(), PP.getSelectorTable(),
+ PP.getBuiltinInfo());
bool disableValid = false;
if (::getenv("LIBCLANG_DISABLE_PCH_VALIDATION"))
disableValid = true;
- AST->Reader = new ASTReader(PP, Context, PCHContainerRdr, { },
+ AST->Reader = new ASTReader(PP, AST->Ctx.get(), PCHContainerRdr, { },
/*isysroot=*/"",
/*DisableValidation=*/disableValid,
AllowPCHWithCompilerErrors);
AST->Reader->setListener(llvm::make_unique<ASTInfoCollector>(
- *AST->PP, Context, *AST->HSOpts, *AST->PPOpts, *AST->LangOpts,
+ *AST->PP, AST->Ctx.get(), *AST->HSOpts, *AST->PPOpts, *AST->LangOpts,
AST->TargetOpts, AST->Target, Counter));
// Attach the AST reader to the AST context as an external AST
@@ -744,7 +747,8 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile(
// AST file as needed.
// We need the external source to be set up before we read the AST, because
// eagerly-deserialized declarations may use it.
- Context.setExternalSource(AST->Reader);
+ if (AST->Ctx)
+ AST->Ctx->setExternalSource(AST->Reader);
switch (AST->Reader->ReadAST(Filename, serialization::MK_MainFile,
SourceLocation(), ASTReader::ARR_None)) {
@@ -766,15 +770,18 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile(
PP.setCounterValue(Counter);
// Create an AST consumer, even though it isn't used.
- AST->Consumer.reset(new ASTConsumer);
-
+ if (ToLoad >= LoadASTOnly)
+ AST->Consumer.reset(new ASTConsumer);
+
// Create a semantic analysis object and tell the AST reader about it.
- AST->TheSema.reset(new Sema(PP, Context, *AST->Consumer));
- AST->TheSema->Initialize();
- AST->Reader->InitializeSema(*AST->TheSema);
+ if (ToLoad >= LoadEverything) {
+ AST->TheSema.reset(new Sema(PP, *AST->Ctx, *AST->Consumer));
+ AST->TheSema->Initialize();
+ AST->Reader->InitializeSema(*AST->TheSema);
+ }
// Tell the diagnostic client that we have started a source file.
- AST->getDiagnostics().getClient()->BeginSourceFile(Context.getLangOpts(),&PP);
+ AST->getDiagnostics().getClient()->BeginSourceFile(PP.getLangOpts(), &PP);
return AST;
}
@@ -1638,7 +1645,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine(
&StoredDiagnostics, nullptr);
CI = clang::createInvocationFromCommandLine(
- llvm::makeArrayRef(ArgBegin, ArgEnd), Diags);
+ llvm::makeArrayRef(ArgBegin, ArgEnd), Diags, VFS);
if (!CI)
return nullptr;
}
diff --git a/lib/Frontend/ChainedIncludesSource.cpp b/lib/Frontend/ChainedIncludesSource.cpp
index b984c2ed0dd5..534c7587f48d 100644
--- a/lib/Frontend/ChainedIncludesSource.cpp
+++ b/lib/Frontend/ChainedIncludesSource.cpp
@@ -83,7 +83,7 @@ createASTReader(CompilerInstance &CI, StringRef pchFile,
ASTDeserializationListener *deserialListener = nullptr) {
Preprocessor &PP = CI.getPreprocessor();
std::unique_ptr<ASTReader> Reader;
- Reader.reset(new ASTReader(PP, CI.getASTContext(),
+ Reader.reset(new ASTReader(PP, &CI.getASTContext(),
CI.getPCHContainerReader(),
/*Extensions=*/{ },
/*isysroot=*/"", /*DisableValidation=*/true));
diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp
index e5da2ae4f22e..bb6a665cb456 100644
--- a/lib/Frontend/CompilerInstance.cpp
+++ b/lib/Frontend/CompilerInstance.cpp
@@ -517,7 +517,7 @@ IntrusiveRefCntPtr<ASTReader> CompilerInstance::createPCHExternalASTSource(
HeaderSearchOptions &HSOpts = PP.getHeaderSearchInfo().getHeaderSearchOpts();
IntrusiveRefCntPtr<ASTReader> Reader(new ASTReader(
- PP, Context, PCHContainerRdr, Extensions,
+ PP, &Context, PCHContainerRdr, Extensions,
Sysroot.empty() ? "" : Sysroot.data(), DisablePCHValidation,
AllowPCHWithCompilerErrors, /*AllowConfigurationMismatch*/ false,
HSOpts.ModulesValidateSystemHeaders, UseGlobalModuleIndex));
@@ -825,8 +825,11 @@ bool CompilerInstance::InitializeSourceManager(
const FrontendInputFile &Input, DiagnosticsEngine &Diags,
FileManager &FileMgr, SourceManager &SourceMgr, HeaderSearch *HS,
DependencyOutputOptions &DepOpts, const FrontendOptions &Opts) {
- SrcMgr::CharacteristicKind
- Kind = Input.isSystem() ? SrcMgr::C_System : SrcMgr::C_User;
+ SrcMgr::CharacteristicKind Kind =
+ Input.getKind().getFormat() == InputKind::ModuleMap
+ ? Input.isSystem() ? SrcMgr::C_System_ModuleMap
+ : SrcMgr::C_User_ModuleMap
+ : Input.isSystem() ? SrcMgr::C_System : SrcMgr::C_User;
if (Input.isBuffer()) {
SourceMgr.setMainFileID(SourceMgr.createFileID(
@@ -933,8 +936,9 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) {
if (!hasTarget())
return false;
- // Create TargetInfo for the other side of CUDA compilation.
- if (getLangOpts().CUDA && !getFrontendOpts().AuxTriple.empty()) {
+ // Create TargetInfo for the other side of CUDA and OpenMP compilation.
+ if ((getLangOpts().CUDA || getLangOpts().OpenMPIsDevice) &&
+ !getFrontendOpts().AuxTriple.empty()) {
auto TO = std::make_shared<TargetOptions>();
TO->Triple = getFrontendOpts().AuxTriple;
TO->HostTriple = getTarget().getTriple().str();
@@ -1469,7 +1473,7 @@ void CompilerInstance::createModuleManager() {
"Reading modules",
*FrontendTimerGroup);
ModuleManager = new ASTReader(
- getPreprocessor(), getASTContext(), getPCHContainerReader(),
+ getPreprocessor(), &getASTContext(), getPCHContainerReader(),
getFrontendOpts().ModuleFileExtensions,
Sysroot.empty() ? "" : Sysroot.c_str(), PPOpts.DisablePCHValidation,
/*AllowASTWithCompilerErrors=*/false,
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 6254b0013bab..00f6b9b46f03 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -476,6 +476,10 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
OPT_fexperimental_new_pass_manager, OPT_fno_experimental_new_pass_manager,
/* Default */ false);
+ Opts.DebugPassManager =
+ Args.hasFlag(OPT_fdebug_pass_manager, OPT_fno_debug_pass_manager,
+ /* Default */ false);
+
if (Arg *A = Args.getLastArg(OPT_fveclib)) {
StringRef Name = A->getValue();
if (Name == "Accelerate")
@@ -668,7 +672,6 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.MSVolatile = Args.hasArg(OPT_fms_volatile);
- Opts.VectorizeBB = Args.hasArg(OPT_vectorize_slp_aggressive);
Opts.VectorizeLoop = Args.hasArg(OPT_vectorize_loops);
Opts.VectorizeSLP = Args.hasArg(OPT_vectorize_slp);
@@ -906,12 +909,18 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.DiagnosticsWithHotness =
Args.hasArg(options::OPT_fdiagnostics_show_hotness);
bool UsingSampleProfile = !Opts.SampleProfileFile.empty();
+ bool UsingProfile = UsingSampleProfile ||
+ (Opts.getProfileUse() != CodeGenOptions::ProfileNone);
- if (Opts.DiagnosticsWithHotness &&
- Opts.getProfileUse() == CodeGenOptions::ProfileNone &&
- !UsingSampleProfile) {
- Diags.Report(diag::warn_drv_fdiagnostics_show_hotness_requires_pgo);
- }
+ if (Opts.DiagnosticsWithHotness && !UsingProfile)
+ Diags.Report(diag::warn_drv_diagnostics_hotness_requires_pgo)
+ << "-fdiagnostics-show-hotness";
+
+ Opts.DiagnosticsHotnessThreshold = getLastArgUInt64Value(
+ Args, options::OPT_fdiagnostics_hotness_threshold_EQ, 0);
+ if (Opts.DiagnosticsHotnessThreshold > 0 && !UsingProfile)
+ Diags.Report(diag::warn_drv_diagnostics_hotness_requires_pgo)
+ << "-fdiagnostics-hotness-threshold=";
// If the user requested to use a sample profile for PGO, then the
// backend will need to track source location information so the profile
@@ -2106,6 +2115,8 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.AlignedAllocation =
Args.hasFlag(OPT_faligned_allocation, OPT_fno_aligned_allocation,
Opts.AlignedAllocation);
+ Opts.AlignedAllocationUnavailable =
+ Opts.AlignedAllocation && Args.hasArg(OPT_aligned_alloc_unavailable);
Opts.NewAlignOverride =
getLastArgIntValue(Args, OPT_fnew_alignment_EQ, 0, Diags);
if (Opts.NewAlignOverride && !llvm::isPowerOf2_32(Opts.NewAlignOverride)) {
@@ -2557,7 +2568,7 @@ static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args,
Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args)
<< Value;
else
- Opts.EABIVersion = Value;
+ Opts.EABIVersion = EABIVersion;
}
Opts.CPU = Args.getLastArgValue(OPT_target_cpu);
Opts.FPMath = Args.getLastArgValue(OPT_mfpmath);
@@ -2644,6 +2655,10 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
Res.getTargetOpts().HostTriple = Res.getFrontendOpts().AuxTriple;
}
+ // Set the triple of the host for OpenMP device compile.
+ if (LangOpts.OpenMPIsDevice)
+ Res.getTargetOpts().HostTriple = Res.getFrontendOpts().AuxTriple;
+
// FIXME: Override value name discarding when asan or msan is used because the
// backend passes depend on the name of the alloca in order to print out
// names.
diff --git a/lib/Frontend/CreateInvocationFromCommandLine.cpp b/lib/Frontend/CreateInvocationFromCommandLine.cpp
index 49d459e78c45..c3ce7ce2b742 100644
--- a/lib/Frontend/CreateInvocationFromCommandLine.cpp
+++ b/lib/Frontend/CreateInvocationFromCommandLine.cpp
@@ -31,8 +31,8 @@ using namespace llvm::opt;
/// \return A CompilerInvocation, or 0 if none was built for the given
/// argument vector.
std::unique_ptr<CompilerInvocation> clang::createInvocationFromCommandLine(
- ArrayRef<const char *> ArgList,
- IntrusiveRefCntPtr<DiagnosticsEngine> Diags) {
+ ArrayRef<const char *> ArgList, IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
+ IntrusiveRefCntPtr<vfs::FileSystem> VFS) {
if (!Diags.get()) {
// No diagnostics engine was provided, so create our own diagnostics object
// with the default options.
@@ -46,7 +46,7 @@ std::unique_ptr<CompilerInvocation> clang::createInvocationFromCommandLine(
// FIXME: We shouldn't have to pass in the path info.
driver::Driver TheDriver(Args[0], llvm::sys::getDefaultTargetTriple(),
- *Diags);
+ *Diags, VFS);
// Don't check that inputs exist, they may have been remapped.
TheDriver.setCheckInputsExist(false);
diff --git a/lib/Frontend/DependencyFile.cpp b/lib/Frontend/DependencyFile.cpp
index bd14c53e4d15..561eb9c4a316 100644
--- a/lib/Frontend/DependencyFile.cpp
+++ b/lib/Frontend/DependencyFile.cpp
@@ -55,8 +55,8 @@ struct DepCollectorPPCallbacks : public PPCallbacks {
llvm::sys::path::remove_leading_dotslash(FE->getName());
DepCollector.maybeAddDependency(Filename, /*FromModule*/false,
- FileType != SrcMgr::C_User,
- /*IsModuleFile*/false, /*IsMissing*/false);
+ isSystem(FileType),
+ /*IsModuleFile*/false, /*IsMissing*/false);
}
void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
@@ -265,7 +265,7 @@ bool DFGImpl::FileMatchesDepCriteria(const char *Filename,
if (IncludeSystemHeaders)
return true;
- return FileType == SrcMgr::C_User;
+ return !isSystem(FileType);
}
void DFGImpl::FileChanged(SourceLocation Loc,
diff --git a/lib/Frontend/DiagnosticRenderer.cpp b/lib/Frontend/DiagnosticRenderer.cpp
index 177feac97441..e3263843e29b 100644
--- a/lib/Frontend/DiagnosticRenderer.cpp
+++ b/lib/Frontend/DiagnosticRenderer.cpp
@@ -76,20 +76,19 @@ static void mergeFixits(ArrayRef<FixItHint> FixItHints,
}
}
-void DiagnosticRenderer::emitDiagnostic(SourceLocation Loc,
+void DiagnosticRenderer::emitDiagnostic(FullSourceLoc Loc,
DiagnosticsEngine::Level Level,
StringRef Message,
ArrayRef<CharSourceRange> Ranges,
ArrayRef<FixItHint> FixItHints,
- const SourceManager *SM,
DiagOrStoredDiag D) {
- assert(SM || Loc.isInvalid());
+ assert(Loc.hasManager() || Loc.isInvalid());
beginDiagnostic(D, Level);
if (!Loc.isValid())
// If we have no source location, just emit the diagnostic message.
- emitDiagnosticMessage(Loc, PresumedLoc(), Level, Message, Ranges, SM, D);
+ emitDiagnosticMessage(Loc, PresumedLoc(), Level, Message, Ranges, D);
else {
// Get the ranges into a local array we can hack on.
SmallVector<CharSourceRange, 20> MutableRanges(Ranges.begin(),
@@ -97,7 +96,7 @@ void DiagnosticRenderer::emitDiagnostic(SourceLocation Loc,
SmallVector<FixItHint, 8> MergedFixits;
if (!FixItHints.empty()) {
- mergeFixits(FixItHints, *SM, LangOpts, MergedFixits);
+ mergeFixits(FixItHints, Loc.getManager(), LangOpts, MergedFixits);
FixItHints = MergedFixits;
}
@@ -107,25 +106,25 @@ void DiagnosticRenderer::emitDiagnostic(SourceLocation Loc,
if (I->RemoveRange.isValid())
MutableRanges.push_back(I->RemoveRange);
- SourceLocation UnexpandedLoc = Loc;
+ FullSourceLoc UnexpandedLoc = Loc;
// Find the ultimate expansion location for the diagnostic.
- Loc = SM->getFileLoc(Loc);
+ Loc = Loc.getFileLoc();
- PresumedLoc PLoc = SM->getPresumedLoc(Loc, DiagOpts->ShowPresumedLoc);
+ PresumedLoc PLoc = Loc.getPresumedLoc(DiagOpts->ShowPresumedLoc);
// First, if this diagnostic is not in the main file, print out the
// "included from" lines.
- emitIncludeStack(Loc, PLoc, Level, *SM);
+ emitIncludeStack(Loc, PLoc, Level);
// Next, emit the actual diagnostic message and caret.
- emitDiagnosticMessage(Loc, PLoc, Level, Message, Ranges, SM, D);
- emitCaret(Loc, Level, MutableRanges, FixItHints, *SM);
+ emitDiagnosticMessage(Loc, PLoc, Level, Message, Ranges, D);
+ emitCaret(Loc, Level, MutableRanges, FixItHints);
// If this location is within a macro, walk from UnexpandedLoc up to Loc
// and produce a macro backtrace.
if (UnexpandedLoc.isValid() && UnexpandedLoc.isMacroID()) {
- emitMacroExpansions(UnexpandedLoc, Level, MutableRanges, FixItHints, *SM);
+ emitMacroExpansions(UnexpandedLoc, Level, MutableRanges, FixItHints);
}
}
@@ -139,15 +138,12 @@ void DiagnosticRenderer::emitDiagnostic(SourceLocation Loc,
void DiagnosticRenderer::emitStoredDiagnostic(StoredDiagnostic &Diag) {
emitDiagnostic(Diag.getLocation(), Diag.getLevel(), Diag.getMessage(),
Diag.getRanges(), Diag.getFixIts(),
- Diag.getLocation().isValid() ? &Diag.getLocation().getManager()
- : nullptr,
&Diag);
}
void DiagnosticRenderer::emitBasicNote(StringRef Message) {
- emitDiagnosticMessage(
- SourceLocation(), PresumedLoc(), DiagnosticsEngine::Note, Message,
- None, nullptr, DiagOrStoredDiag());
+ emitDiagnosticMessage(FullSourceLoc(), PresumedLoc(), DiagnosticsEngine::Note,
+ Message, None, DiagOrStoredDiag());
}
/// \brief Prints an include stack when appropriate for a particular
@@ -161,12 +157,11 @@ void DiagnosticRenderer::emitBasicNote(StringRef Message) {
/// \param Loc The diagnostic location.
/// \param PLoc The presumed location of the diagnostic location.
/// \param Level The diagnostic level of the message this stack pertains to.
-void DiagnosticRenderer::emitIncludeStack(SourceLocation Loc,
- PresumedLoc PLoc,
- DiagnosticsEngine::Level Level,
- const SourceManager &SM) {
- SourceLocation IncludeLoc =
- PLoc.isInvalid() ? SourceLocation() : PLoc.getIncludeLoc();
+void DiagnosticRenderer::emitIncludeStack(FullSourceLoc Loc, PresumedLoc PLoc,
+ DiagnosticsEngine::Level Level) {
+ FullSourceLoc IncludeLoc =
+ PLoc.isInvalid() ? FullSourceLoc()
+ : FullSourceLoc(PLoc.getIncludeLoc(), Loc.getManager());
// Skip redundant include stacks altogether.
if (LastIncludeLoc == IncludeLoc)
@@ -178,74 +173,70 @@ void DiagnosticRenderer::emitIncludeStack(SourceLocation Loc,
return;
if (IncludeLoc.isValid())
- emitIncludeStackRecursively(IncludeLoc, SM);
+ emitIncludeStackRecursively(IncludeLoc);
else {
- emitModuleBuildStack(SM);
- emitImportStack(Loc, SM);
+ emitModuleBuildStack(Loc.getManager());
+ emitImportStack(Loc);
}
}
/// \brief Helper to recursivly walk up the include stack and print each layer
/// on the way back down.
-void DiagnosticRenderer::emitIncludeStackRecursively(SourceLocation Loc,
- const SourceManager &SM) {
+void DiagnosticRenderer::emitIncludeStackRecursively(FullSourceLoc Loc) {
if (Loc.isInvalid()) {
- emitModuleBuildStack(SM);
+ emitModuleBuildStack(Loc.getManager());
return;
}
-
- PresumedLoc PLoc = SM.getPresumedLoc(Loc, DiagOpts->ShowPresumedLoc);
+
+ PresumedLoc PLoc = Loc.getPresumedLoc(DiagOpts->ShowPresumedLoc);
if (PLoc.isInvalid())
return;
// If this source location was imported from a module, print the module
// import stack rather than the
// FIXME: We want submodule granularity here.
- std::pair<SourceLocation, StringRef> Imported = SM.getModuleImportLoc(Loc);
+ std::pair<FullSourceLoc, StringRef> Imported = Loc.getModuleImportLoc();
if (!Imported.second.empty()) {
// This location was imported by a module. Emit the module import stack.
- emitImportStackRecursively(Imported.first, Imported.second, SM);
+ emitImportStackRecursively(Imported.first, Imported.second);
return;
}
// Emit the other include frames first.
- emitIncludeStackRecursively(PLoc.getIncludeLoc(), SM);
-
+ emitIncludeStackRecursively(
+ FullSourceLoc(PLoc.getIncludeLoc(), Loc.getManager()));
+
// Emit the inclusion text/note.
- emitIncludeLocation(Loc, PLoc, SM);
+ emitIncludeLocation(Loc, PLoc);
}
/// \brief Emit the module import stack associated with the current location.
-void DiagnosticRenderer::emitImportStack(SourceLocation Loc,
- const SourceManager &SM) {
+void DiagnosticRenderer::emitImportStack(FullSourceLoc Loc) {
if (Loc.isInvalid()) {
- emitModuleBuildStack(SM);
+ emitModuleBuildStack(Loc.getManager());
return;
}
- std::pair<SourceLocation, StringRef> NextImportLoc
- = SM.getModuleImportLoc(Loc);
- emitImportStackRecursively(NextImportLoc.first, NextImportLoc.second, SM);
+ std::pair<FullSourceLoc, StringRef> NextImportLoc = Loc.getModuleImportLoc();
+ emitImportStackRecursively(NextImportLoc.first, NextImportLoc.second);
}
/// \brief Helper to recursivly walk up the import stack and print each layer
/// on the way back down.
-void DiagnosticRenderer::emitImportStackRecursively(SourceLocation Loc,
- StringRef ModuleName,
- const SourceManager &SM) {
+void DiagnosticRenderer::emitImportStackRecursively(FullSourceLoc Loc,
+ StringRef ModuleName) {
if (ModuleName.empty()) {
return;
}
- PresumedLoc PLoc = SM.getPresumedLoc(Loc, DiagOpts->ShowPresumedLoc);
+ PresumedLoc PLoc = Loc.getPresumedLoc(DiagOpts->ShowPresumedLoc);
// Emit the other import frames first.
- std::pair<SourceLocation, StringRef> NextImportLoc
- = SM.getModuleImportLoc(Loc);
- emitImportStackRecursively(NextImportLoc.first, NextImportLoc.second, SM);
+ std::pair<FullSourceLoc, StringRef> NextImportLoc = Loc.getModuleImportLoc();
+ emitImportStackRecursively(NextImportLoc.first, NextImportLoc.second);
// Emit the inclusion text/note.
- emitImportLocation(Loc, PLoc, ModuleName, SM);
+ emitImportLocation(Loc, PLoc, ModuleName);
}
/// \brief Emit the module build stack, for cases where a module is (re-)built
@@ -253,13 +244,9 @@ void DiagnosticRenderer::emitImportStackRecursively(SourceLocation Loc,
void DiagnosticRenderer::emitModuleBuildStack(const SourceManager &SM) {
ModuleBuildStack Stack = SM.getModuleBuildStack();
for (unsigned I = 0, N = Stack.size(); I != N; ++I) {
- const SourceManager &CurSM = Stack[I].second.getManager();
- SourceLocation CurLoc = Stack[I].second;
- emitBuildingModuleLocation(CurLoc,
- CurSM.getPresumedLoc(CurLoc,
+ emitBuildingModuleLocation(Stack[I].second, Stack[I].second.getPresumedLoc(
DiagOpts->ShowPresumedLoc),
- Stack[I].first,
- CurSM);
+ Stack[I].first);
}
}
@@ -348,12 +335,12 @@ static void computeCommonMacroArgExpansionFileIDs(
// in the same expansion as the caret; otherwise, we crawl to the top of
// each chain. Two locations are part of the same macro expansion
// iff the FileID is the same.
-static void mapDiagnosticRanges(
- SourceLocation CaretLoc,
- ArrayRef<CharSourceRange> Ranges,
- SmallVectorImpl<CharSourceRange> &SpellingRanges,
- const SourceManager *SM) {
- FileID CaretLocFileID = SM->getFileID(CaretLoc);
+static void
+mapDiagnosticRanges(FullSourceLoc CaretLoc, ArrayRef<CharSourceRange> Ranges,
+ SmallVectorImpl<CharSourceRange> &SpellingRanges) {
+ FileID CaretLocFileID = CaretLoc.getFileID();
+
+ const SourceManager *SM = &CaretLoc.getManager();
for (auto I = Ranges.begin(), E = Ranges.end(); I != E; ++I) {
if (I->isInvalid()) continue;
@@ -404,42 +391,39 @@ static void mapDiagnosticRanges(
}
}
-void DiagnosticRenderer::emitCaret(SourceLocation Loc,
+void DiagnosticRenderer::emitCaret(FullSourceLoc Loc,
DiagnosticsEngine::Level Level,
ArrayRef<CharSourceRange> Ranges,
- ArrayRef<FixItHint> Hints,
- const SourceManager &SM) {
+ ArrayRef<FixItHint> Hints) {
SmallVector<CharSourceRange, 4> SpellingRanges;
- mapDiagnosticRanges(Loc, Ranges, SpellingRanges, &SM);
- emitCodeContext(Loc, Level, SpellingRanges, Hints, SM);
+ mapDiagnosticRanges(Loc, Ranges, SpellingRanges);
+ emitCodeContext(Loc, Level, SpellingRanges, Hints);
}
/// \brief A helper function for emitMacroExpansion to print the
/// macro expansion message
void DiagnosticRenderer::emitSingleMacroExpansion(
- SourceLocation Loc,
- DiagnosticsEngine::Level Level,
- ArrayRef<CharSourceRange> Ranges,
- const SourceManager &SM) {
+ FullSourceLoc Loc, DiagnosticsEngine::Level Level,
+ ArrayRef<CharSourceRange> Ranges) {
// Find the spelling location for the macro definition. We must use the
// spelling location here to avoid emitting a macro backtrace for the note.
- SourceLocation SpellingLoc = SM.getSpellingLoc(Loc);
+ FullSourceLoc SpellingLoc = Loc.getSpellingLoc();
// Map the ranges into the FileID of the diagnostic location.
SmallVector<CharSourceRange, 4> SpellingRanges;
- mapDiagnosticRanges(Loc, Ranges, SpellingRanges, &SM);
+ mapDiagnosticRanges(Loc, Ranges, SpellingRanges);
SmallString<100> MessageStorage;
llvm::raw_svector_ostream Message(MessageStorage);
- StringRef MacroName =
- Lexer::getImmediateMacroNameForDiagnostics(Loc, SM, LangOpts);
+ StringRef MacroName = Lexer::getImmediateMacroNameForDiagnostics(
+ Loc, Loc.getManager(), LangOpts);
if (MacroName.empty())
Message << "expanded from here";
else
Message << "expanded from macro '" << MacroName << "'";
emitDiagnostic(SpellingLoc, DiagnosticsEngine::Note, Message.str(),
- SpellingRanges, None, &SM);
+ SpellingRanges, None);
}
/// Check that the macro argument location of Loc starts with ArgumentLoc.
@@ -473,13 +457,12 @@ static bool checkRangeForMacroArgExpansion(CharSourceRange Range,
/// A helper function to check if the current ranges are all inside the same
/// macro argument expansion as Loc.
-static bool checkRangesForMacroArgExpansion(SourceLocation Loc,
- ArrayRef<CharSourceRange> Ranges,
- const SourceManager &SM) {
+static bool checkRangesForMacroArgExpansion(FullSourceLoc Loc,
+ ArrayRef<CharSourceRange> Ranges) {
assert(Loc.isMacroID() && "Must be a macro expansion!");
SmallVector<CharSourceRange, 4> SpellingRanges;
- mapDiagnosticRanges(Loc, Ranges, SpellingRanges, &SM);
+ mapDiagnosticRanges(Loc, Ranges, SpellingRanges);
/// Count all valid ranges.
unsigned ValidCount = 0;
@@ -490,15 +473,15 @@ static bool checkRangesForMacroArgExpansion(SourceLocation Loc,
return false;
/// To store the source location of the argument location.
- SourceLocation ArgumentLoc;
+ FullSourceLoc ArgumentLoc;
/// Set the ArgumentLoc to the beginning location of the expansion of Loc
/// so to check if the ranges expands to the same beginning location.
- if (!SM.isMacroArgExpansion(Loc,&ArgumentLoc))
+ if (!Loc.isMacroArgExpansion(&ArgumentLoc))
return false;
for (auto I = SpellingRanges.begin(), E = SpellingRanges.end(); I != E; ++I) {
- if (!checkRangeForMacroArgExpansion(*I, SM, ArgumentLoc))
+ if (!checkRangeForMacroArgExpansion(*I, Loc.getManager(), ArgumentLoc))
return false;
}
@@ -516,34 +499,33 @@ static bool checkRangesForMacroArgExpansion(SourceLocation Loc,
/// \param Level The diagnostic level currently being emitted.
/// \param Ranges The underlined ranges for this code snippet.
/// \param Hints The FixIt hints active for this diagnostic.
-void DiagnosticRenderer::emitMacroExpansions(SourceLocation Loc,
+void DiagnosticRenderer::emitMacroExpansions(FullSourceLoc Loc,
DiagnosticsEngine::Level Level,
ArrayRef<CharSourceRange> Ranges,
- ArrayRef<FixItHint> Hints,
- const SourceManager &SM) {
+ ArrayRef<FixItHint> Hints) {
assert(Loc.isValid() && "must have a valid source location here");
// Produce a stack of macro backtraces.
- SmallVector<SourceLocation, 8> LocationStack;
+ SmallVector<FullSourceLoc, 8> LocationStack;
unsigned IgnoredEnd = 0;
while (Loc.isMacroID()) {
// If this is the expansion of a macro argument, point the caret at the
// use of the argument in the definition of the macro, not the expansion.
- if (SM.isMacroArgExpansion(Loc))
- LocationStack.push_back(SM.getImmediateExpansionRange(Loc).first);
+ if (Loc.isMacroArgExpansion())
+ LocationStack.push_back(Loc.getImmediateExpansionRange().first);
else
LocationStack.push_back(Loc);
- if (checkRangesForMacroArgExpansion(Loc, Ranges, SM))
+ if (checkRangesForMacroArgExpansion(Loc, Ranges))
IgnoredEnd = LocationStack.size();
- Loc = SM.getImmediateMacroCallerLoc(Loc);
+ Loc = Loc.getImmediateMacroCallerLoc();
// Once the location no longer points into a macro, try stepping through
// the last found location. This sometimes produces additional useful
// backtraces.
if (Loc.isFileID())
- Loc = SM.getImmediateMacroCallerLoc(LocationStack.back());
+ Loc = LocationStack.back().getImmediateMacroCallerLoc();
assert(Loc.isValid() && "must have a valid source location here");
}
@@ -555,7 +537,7 @@ void DiagnosticRenderer::emitMacroExpansions(SourceLocation Loc,
if (MacroDepth <= MacroLimit || MacroLimit == 0) {
for (auto I = LocationStack.rbegin(), E = LocationStack.rend();
I != E; ++I)
- emitSingleMacroExpansion(*I, Level, Ranges, SM);
+ emitSingleMacroExpansion(*I, Level, Ranges);
return;
}
@@ -565,7 +547,7 @@ void DiagnosticRenderer::emitMacroExpansions(SourceLocation Loc,
for (auto I = LocationStack.rbegin(),
E = LocationStack.rbegin() + MacroStartMessages;
I != E; ++I)
- emitSingleMacroExpansion(*I, Level, Ranges, SM);
+ emitSingleMacroExpansion(*I, Level, Ranges);
SmallString<200> MessageStorage;
llvm::raw_svector_ostream Message(MessageStorage);
@@ -577,26 +559,24 @@ void DiagnosticRenderer::emitMacroExpansions(SourceLocation Loc,
for (auto I = LocationStack.rend() - MacroEndMessages,
E = LocationStack.rend();
I != E; ++I)
- emitSingleMacroExpansion(*I, Level, Ranges, SM);
+ emitSingleMacroExpansion(*I, Level, Ranges);
}
DiagnosticNoteRenderer::~DiagnosticNoteRenderer() {}
-void DiagnosticNoteRenderer::emitIncludeLocation(SourceLocation Loc,
- PresumedLoc PLoc,
- const SourceManager &SM) {
+void DiagnosticNoteRenderer::emitIncludeLocation(FullSourceLoc Loc,
+ PresumedLoc PLoc) {
// Generate a note indicating the include location.
SmallString<200> MessageStorage;
llvm::raw_svector_ostream Message(MessageStorage);
Message << "in file included from " << PLoc.getFilename() << ':'
<< PLoc.getLine() << ":";
- emitNote(Loc, Message.str(), &SM);
+ emitNote(Loc, Message.str());
}
-void DiagnosticNoteRenderer::emitImportLocation(SourceLocation Loc,
+void DiagnosticNoteRenderer::emitImportLocation(FullSourceLoc Loc,
PresumedLoc PLoc,
- StringRef ModuleName,
- const SourceManager &SM) {
+ StringRef ModuleName) {
// Generate a note indicating the include location.
SmallString<200> MessageStorage;
llvm::raw_svector_ostream Message(MessageStorage);
@@ -605,14 +585,12 @@ void DiagnosticNoteRenderer::emitImportLocation(SourceLocation Loc,
Message << "' imported from " << PLoc.getFilename() << ':'
<< PLoc.getLine();
Message << ":";
- emitNote(Loc, Message.str(), &SM);
+ emitNote(Loc, Message.str());
}
-void
-DiagnosticNoteRenderer::emitBuildingModuleLocation(SourceLocation Loc,
- PresumedLoc PLoc,
- StringRef ModuleName,
- const SourceManager &SM) {
+void DiagnosticNoteRenderer::emitBuildingModuleLocation(FullSourceLoc Loc,
+ PresumedLoc PLoc,
+ StringRef ModuleName) {
// Generate a note indicating the include location.
SmallString<200> MessageStorage;
llvm::raw_svector_ostream Message(MessageStorage);
@@ -621,5 +599,5 @@ DiagnosticNoteRenderer::emitBuildingModuleLocation(SourceLocation Loc,
<< PLoc.getFilename() << ':' << PLoc.getLine() << ":";
else
Message << "while building module '" << ModuleName << "':";
- emitNote(Loc, Message.str(), &SM);
+ emitNote(Loc, Message.str());
}
diff --git a/lib/Frontend/FrontendAction.cpp b/lib/Frontend/FrontendAction.cpp
index f81a06b31869..704d51509851 100644
--- a/lib/Frontend/FrontendAction.cpp
+++ b/lib/Frontend/FrontendAction.cpp
@@ -200,12 +200,12 @@ FrontendAction::CreateWrappedASTConsumer(CompilerInstance &CI,
///
/// \param CI The compiler instance.
/// \param InputFile Populated with the filename from the line marker.
-/// \param AddLineNote If \c true, add a line note corresponding to this line
-/// directive. Only use this if the directive will not actually be
-/// visited by the preprocessor.
+/// \param IsModuleMap If \c true, add a line note corresponding to this line
+/// directive. (We need to do this because the directive will not be
+/// visited by the preprocessor.)
static SourceLocation ReadOriginalFileName(CompilerInstance &CI,
std::string &InputFile,
- bool AddLineNote = false) {
+ bool IsModuleMap = false) {
auto &SourceMgr = CI.getSourceManager();
auto MainFileID = SourceMgr.getMainFileID();
@@ -231,7 +231,7 @@ static SourceLocation ReadOriginalFileName(CompilerInstance &CI,
unsigned LineNo;
SourceLocation LineNoLoc = T.getLocation();
- if (AddLineNote) {
+ if (IsModuleMap) {
llvm::SmallString<16> Buffer;
if (Lexer::getSpelling(LineNoLoc, Buffer, SourceMgr, CI.getLangOpts())
.getAsInteger(10, LineNo))
@@ -250,10 +250,10 @@ static SourceLocation ReadOriginalFileName(CompilerInstance &CI,
return SourceLocation();
InputFile = Literal.GetString().str();
- if (AddLineNote)
+ if (IsModuleMap)
CI.getSourceManager().AddLineNote(
LineNoLoc, LineNo, SourceMgr.getLineTableFilenameID(InputFile), false,
- false, SrcMgr::C_User);
+ false, SrcMgr::C_User_ModuleMap);
return T.getLocation();
}
@@ -403,7 +403,7 @@ static bool loadModuleMapForModuleBuild(CompilerInstance &CI, bool IsSystem,
Offset = 0;
if (IsPreprocessed) {
SourceLocation EndOfLineMarker =
- ReadOriginalFileName(CI, PresumedModuleMapFile, /*AddLineNote*/true);
+ ReadOriginalFileName(CI, PresumedModuleMapFile, /*IsModuleMap*/ true);
if (EndOfLineMarker.isValid())
Offset = CI.getSourceManager().getDecomposedLoc(EndOfLineMarker).second;
}
@@ -536,8 +536,8 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
ASTDiags->setClient(Diags->getClient(), /*OwnsClient*/false);
std::unique_ptr<ASTUnit> AST = ASTUnit::LoadFromASTFile(
- InputFile, CI.getPCHContainerReader(), ASTDiags, CI.getFileSystemOpts(),
- CI.getCodeGenOpts().DebugTypeExtRefs);
+ InputFile, CI.getPCHContainerReader(), ASTUnit::LoadPreprocessorOnly,
+ ASTDiags, CI.getFileSystemOpts(), CI.getCodeGenOpts().DebugTypeExtRefs);
if (!AST)
goto failure;
@@ -547,27 +547,36 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
CI.getPreprocessorOpts() = AST->getPreprocessorOpts();
CI.getLangOpts() = AST->getLangOpts();
- // Preload all the module files loaded transitively by the AST unit.
- if (auto ASTReader = AST->getASTReader()) {
- auto &MM = ASTReader->getModuleManager();
- for (ModuleFile &MF : MM)
- if (&MF != &MM.getPrimaryModule())
- CI.getFrontendOpts().ModuleFiles.push_back(MF.FileName);
- }
- // FIXME: Preload module maps loaded by the AST unit.
-
// Set the shared objects, these are reset when we finish processing the
// file, otherwise the CompilerInstance will happily destroy them.
CI.setFileManager(&AST->getFileManager());
CI.createSourceManager(CI.getFileManager());
CI.getSourceManager().initializeForReplay(AST->getSourceManager());
+ // Preload all the module files loaded transitively by the AST unit. Also
+ // load all module map files that were parsed as part of building the AST
+ // unit.
+ if (auto ASTReader = AST->getASTReader()) {
+ auto &MM = ASTReader->getModuleManager();
+ auto &PrimaryModule = MM.getPrimaryModule();
+
+ for (ModuleFile &MF : MM)
+ if (&MF != &PrimaryModule)
+ CI.getFrontendOpts().ModuleFiles.push_back(MF.FileName);
+
+ ASTReader->visitTopLevelModuleMaps(PrimaryModule,
+ [&](const FileEntry *FE) {
+ CI.getFrontendOpts().ModuleMapFiles.push_back(FE->getName());
+ });
+ }
+
// Set up the input file for replay purposes.
auto Kind = AST->getInputKind();
if (Kind.getFormat() == InputKind::ModuleMap) {
Module *ASTModule =
AST->getPreprocessor().getHeaderSearchInfo().lookupModule(
AST->getLangOpts().CurrentModule, /*AllowSearch*/ false);
+ assert(ASTModule && "module file does not define its own module");
Input = FrontendInputFile(ASTModule->PresumedModuleMapFile, Kind);
} else {
auto &SM = CI.getSourceManager();
@@ -590,8 +599,8 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
IntrusiveRefCntPtr<DiagnosticsEngine> Diags(&CI.getDiagnostics());
std::unique_ptr<ASTUnit> AST = ASTUnit::LoadFromASTFile(
- InputFile, CI.getPCHContainerReader(), Diags, CI.getFileSystemOpts(),
- CI.getCodeGenOpts().DebugTypeExtRefs);
+ InputFile, CI.getPCHContainerReader(), ASTUnit::LoadEverything, Diags,
+ CI.getFileSystemOpts(), CI.getCodeGenOpts().DebugTypeExtRefs);
if (!AST)
goto failure;
diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp
index 9621889b27ad..0fbcc1c7399e 100644
--- a/lib/Frontend/FrontendActions.cpp
+++ b/lib/Frontend/FrontendActions.cpp
@@ -230,7 +230,7 @@ void VerifyPCHAction::ExecuteAction() {
bool Preamble = CI.getPreprocessorOpts().PrecompiledPreambleBytes.first != 0;
const std::string &Sysroot = CI.getHeaderSearchOpts().Sysroot;
std::unique_ptr<ASTReader> Reader(new ASTReader(
- CI.getPreprocessor(), CI.getASTContext(), CI.getPCHContainerReader(),
+ CI.getPreprocessor(), &CI.getASTContext(), CI.getPCHContainerReader(),
CI.getFrontendOpts().ModuleFileExtensions,
Sysroot.empty() ? "" : Sysroot.c_str(),
/*DisableValidation*/ false,
diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp
index 08befb33c962..71420df00025 100644
--- a/lib/Frontend/InitPreprocessor.cpp
+++ b/lib/Frontend/InitPreprocessor.cpp
@@ -1043,7 +1043,7 @@ void clang::InitializePreprocessor(
if (InitOpts.UsePredefines) {
// FIXME: This will create multiple definitions for most of the predefined
// macros. This is not the right way to handle this.
- if (LangOpts.CUDA && PP.getAuxTargetInfo())
+ if ((LangOpts.CUDA || LangOpts.OpenMPIsDevice) && PP.getAuxTargetInfo())
InitializePredefinedMacros(*PP.getAuxTargetInfo(), LangOpts, FEOpts,
Builder);
diff --git a/lib/Frontend/ModuleDependencyCollector.cpp b/lib/Frontend/ModuleDependencyCollector.cpp
index 9b34d4211353..ede12aab6e69 100644
--- a/lib/Frontend/ModuleDependencyCollector.cpp
+++ b/lib/Frontend/ModuleDependencyCollector.cpp
@@ -248,7 +248,7 @@ std::error_code ModuleDependencyCollector::copyToRoot(StringRef Src,
// Always map a canonical src path to its real path into the YAML, by doing
// this we map different virtual src paths to the same entry in the VFS
// overlay, which is a way to emulate symlink inside the VFS; this is also
- // needed for correctness, not doing that can lead to module redifinition
+ // needed for correctness, not doing that can lead to module redefinition
// errors.
addFileMapping(VirtualPath, CacheDst);
return std::error_code();
diff --git a/lib/Frontend/SerializedDiagnosticPrinter.cpp b/lib/Frontend/SerializedDiagnosticPrinter.cpp
index b5a5acd8ad9a..7666fe10b381 100644
--- a/lib/Frontend/SerializedDiagnosticPrinter.cpp
+++ b/lib/Frontend/SerializedDiagnosticPrinter.cpp
@@ -63,27 +63,20 @@ public:
~SDiagsRenderer() override {}
protected:
- void emitDiagnosticMessage(SourceLocation Loc,
- PresumedLoc PLoc,
- DiagnosticsEngine::Level Level,
- StringRef Message,
+ void emitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc,
+ DiagnosticsEngine::Level Level, StringRef Message,
ArrayRef<CharSourceRange> Ranges,
- const SourceManager *SM,
DiagOrStoredDiag D) override;
- void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
+ void emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc,
DiagnosticsEngine::Level Level,
- ArrayRef<CharSourceRange> Ranges,
- const SourceManager &SM) override {}
+ ArrayRef<CharSourceRange> Ranges) override {}
- void emitNote(SourceLocation Loc, StringRef Message,
- const SourceManager *SM) override;
+ void emitNote(FullSourceLoc Loc, StringRef Message) override;
- void emitCodeContext(SourceLocation Loc,
- DiagnosticsEngine::Level Level,
- SmallVectorImpl<CharSourceRange>& Ranges,
- ArrayRef<FixItHint> Hints,
- const SourceManager &SM) override;
+ void emitCodeContext(FullSourceLoc Loc, DiagnosticsEngine::Level Level,
+ SmallVectorImpl<CharSourceRange> &Ranges,
+ ArrayRef<FixItHint> Hints) override;
void beginDiagnostic(DiagOrStoredDiag D,
DiagnosticsEngine::Level Level) override;
@@ -193,11 +186,8 @@ private:
void ExitDiagBlock();
/// \brief Emit a DIAG record.
- void EmitDiagnosticMessage(SourceLocation Loc,
- PresumedLoc PLoc,
- DiagnosticsEngine::Level Level,
- StringRef Message,
- const SourceManager *SM,
+ void EmitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc,
+ DiagnosticsEngine::Level Level, StringRef Message,
DiagOrStoredDiag D);
/// \brief Emit FIXIT and SOURCE_RANGE records for a diagnostic.
@@ -220,16 +210,14 @@ private:
/// \brief Emit (lazily) the file string and retrieved the file identifier.
unsigned getEmitFile(const char *Filename);
- /// \brief Add SourceLocation information the specified record.
- void AddLocToRecord(SourceLocation Loc, const SourceManager *SM,
- PresumedLoc PLoc, RecordDataImpl &Record,
- unsigned TokSize = 0);
+ /// \brief Add SourceLocation information the specified record.
+ void AddLocToRecord(FullSourceLoc Loc, PresumedLoc PLoc,
+ RecordDataImpl &Record, unsigned TokSize = 0);
/// \brief Add SourceLocation information the specified record.
- void AddLocToRecord(SourceLocation Loc, RecordDataImpl &Record,
- const SourceManager *SM,
+ void AddLocToRecord(FullSourceLoc Loc, RecordDataImpl &Record,
unsigned TokSize = 0) {
- AddLocToRecord(Loc, SM, SM ? SM->getPresumedLoc(Loc) : PresumedLoc(),
+ AddLocToRecord(Loc, Loc.hasManager() ? Loc.getPresumedLoc() : PresumedLoc(),
Record, TokSize);
}
@@ -350,11 +338,8 @@ static void EmitRecordID(unsigned ID, const char *Name,
Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record);
}
-void SDiagsWriter::AddLocToRecord(SourceLocation Loc,
- const SourceManager *SM,
- PresumedLoc PLoc,
- RecordDataImpl &Record,
- unsigned TokSize) {
+void SDiagsWriter::AddLocToRecord(FullSourceLoc Loc, PresumedLoc PLoc,
+ RecordDataImpl &Record, unsigned TokSize) {
if (PLoc.isInvalid()) {
// Emit a "sentinel" location.
Record.push_back((unsigned)0); // File.
@@ -367,19 +352,19 @@ void SDiagsWriter::AddLocToRecord(SourceLocation Loc,
Record.push_back(getEmitFile(PLoc.getFilename()));
Record.push_back(PLoc.getLine());
Record.push_back(PLoc.getColumn()+TokSize);
- Record.push_back(SM->getFileOffset(Loc));
+ Record.push_back(Loc.getFileOffset());
}
void SDiagsWriter::AddCharSourceRangeToRecord(CharSourceRange Range,
RecordDataImpl &Record,
const SourceManager &SM) {
- AddLocToRecord(Range.getBegin(), Record, &SM);
+ AddLocToRecord(FullSourceLoc(Range.getBegin(), SM), Record);
unsigned TokSize = 0;
if (Range.isTokenRange())
TokSize = Lexer::MeasureTokenLength(Range.getEnd(),
SM, *LangOpts);
-
- AddLocToRecord(Range.getEnd(), Record, &SM, TokSize);
+
+ AddLocToRecord(FullSourceLoc(Range.getEnd(), SM), Record, TokSize);
}
unsigned SDiagsWriter::getEmitFile(const char *FileName){
@@ -606,8 +591,8 @@ void SDiagsWriter::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
if (DiagLevel == DiagnosticsEngine::Note)
EnterDiagBlock();
- EmitDiagnosticMessage(SourceLocation(), PresumedLoc(), DiagLevel,
- State->diagBuf, nullptr, &Info);
+ EmitDiagnosticMessage(FullSourceLoc(), PresumedLoc(), DiagLevel,
+ State->diagBuf, &Info);
if (DiagLevel == DiagnosticsEngine::Note)
ExitDiagBlock();
@@ -618,12 +603,9 @@ void SDiagsWriter::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
assert(Info.hasSourceManager() && LangOpts &&
"Unexpected diagnostic with valid location outside of a source file");
SDiagsRenderer Renderer(*this, *LangOpts, &*State->DiagOpts);
- Renderer.emitDiagnostic(Info.getLocation(), DiagLevel,
- State->diagBuf,
- Info.getRanges(),
- Info.getFixItHints(),
- &Info.getSourceManager(),
- &Info);
+ Renderer.emitDiagnostic(
+ FullSourceLoc(Info.getLocation(), Info.getSourceManager()), DiagLevel,
+ State->diagBuf, Info.getRanges(), Info.getFixItHints(), &Info);
}
static serialized_diags::Level getStableLevel(DiagnosticsEngine::Level Level) {
@@ -641,11 +623,9 @@ static serialized_diags::Level getStableLevel(DiagnosticsEngine::Level Level) {
llvm_unreachable("invalid diagnostic level");
}
-void SDiagsWriter::EmitDiagnosticMessage(SourceLocation Loc,
- PresumedLoc PLoc,
+void SDiagsWriter::EmitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc,
DiagnosticsEngine::Level Level,
StringRef Message,
- const SourceManager *SM,
DiagOrStoredDiag D) {
llvm::BitstreamWriter &Stream = State->Stream;
RecordData &Record = State->Record;
@@ -655,7 +635,7 @@ void SDiagsWriter::EmitDiagnosticMessage(SourceLocation Loc,
Record.clear();
Record.push_back(RECORD_DIAG);
Record.push_back(getStableLevel(Level));
- AddLocToRecord(Loc, SM, PLoc, Record);
+ AddLocToRecord(Loc, PLoc, Record);
if (const Diagnostic *Info = D.dyn_cast<const Diagnostic*>()) {
// Emit the category string lazily and get the category ID.
@@ -672,15 +652,11 @@ void SDiagsWriter::EmitDiagnosticMessage(SourceLocation Loc,
Stream.EmitRecordWithBlob(Abbrevs.get(RECORD_DIAG), Record, Message);
}
-void
-SDiagsRenderer::emitDiagnosticMessage(SourceLocation Loc,
- PresumedLoc PLoc,
- DiagnosticsEngine::Level Level,
- StringRef Message,
- ArrayRef<clang::CharSourceRange> Ranges,
- const SourceManager *SM,
- DiagOrStoredDiag D) {
- Writer.EmitDiagnosticMessage(Loc, PLoc, Level, Message, SM, D);
+void SDiagsRenderer::emitDiagnosticMessage(
+ FullSourceLoc Loc, PresumedLoc PLoc, DiagnosticsEngine::Level Level,
+ StringRef Message, ArrayRef<clang::CharSourceRange> Ranges,
+ DiagOrStoredDiag D) {
+ Writer.EmitDiagnosticMessage(Loc, PLoc, Level, Message, D);
}
void SDiagsWriter::EnterDiagBlock() {
@@ -733,20 +709,18 @@ void SDiagsWriter::EmitCodeContext(SmallVectorImpl<CharSourceRange> &Ranges,
}
}
-void SDiagsRenderer::emitCodeContext(SourceLocation Loc,
+void SDiagsRenderer::emitCodeContext(FullSourceLoc Loc,
DiagnosticsEngine::Level Level,
SmallVectorImpl<CharSourceRange> &Ranges,
- ArrayRef<FixItHint> Hints,
- const SourceManager &SM) {
- Writer.EmitCodeContext(Ranges, Hints, SM);
+ ArrayRef<FixItHint> Hints) {
+ Writer.EmitCodeContext(Ranges, Hints, Loc.getManager());
}
-void SDiagsRenderer::emitNote(SourceLocation Loc, StringRef Message,
- const SourceManager *SM) {
+void SDiagsRenderer::emitNote(FullSourceLoc Loc, StringRef Message) {
Writer.EnterDiagBlock();
- PresumedLoc PLoc = SM ? SM->getPresumedLoc(Loc) : PresumedLoc();
- Writer.EmitDiagnosticMessage(Loc, PLoc, DiagnosticsEngine::Note,
- Message, SM, DiagOrStoredDiag());
+ PresumedLoc PLoc = Loc.hasManager() ? Loc.getPresumedLoc() : PresumedLoc();
+ Writer.EmitDiagnosticMessage(Loc, PLoc, DiagnosticsEngine::Note, Message,
+ DiagOrStoredDiag());
Writer.ExitDiagBlock();
}
diff --git a/lib/Frontend/TextDiagnostic.cpp b/lib/Frontend/TextDiagnostic.cpp
index a24d5768f558..1e12ea5e597a 100644
--- a/lib/Frontend/TextDiagnostic.cpp
+++ b/lib/Frontend/TextDiagnostic.cpp
@@ -672,20 +672,16 @@ TextDiagnostic::TextDiagnostic(raw_ostream &OS,
TextDiagnostic::~TextDiagnostic() {}
-void
-TextDiagnostic::emitDiagnosticMessage(SourceLocation Loc,
- PresumedLoc PLoc,
- DiagnosticsEngine::Level Level,
- StringRef Message,
- ArrayRef<clang::CharSourceRange> Ranges,
- const SourceManager *SM,
- DiagOrStoredDiag D) {
+void TextDiagnostic::emitDiagnosticMessage(
+ FullSourceLoc Loc, PresumedLoc PLoc, DiagnosticsEngine::Level Level,
+ StringRef Message, ArrayRef<clang::CharSourceRange> Ranges,
+ DiagOrStoredDiag D) {
uint64_t StartOfLocationInfo = OS.tell();
// Emit the location of this particular diagnostic.
if (Loc.isValid())
- emitDiagnosticLoc(Loc, PLoc, Level, Ranges, *SM);
-
+ emitDiagnosticLoc(Loc, PLoc, Level, Ranges);
+
if (DiagOpts->ShowColors)
OS.resetColor();
@@ -787,17 +783,16 @@ void TextDiagnostic::emitFilename(StringRef Filename, const SourceManager &SM) {
/// This includes extracting as much location information as is present for
/// the diagnostic and printing it, as well as any include stack or source
/// ranges necessary.
-void TextDiagnostic::emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
+void TextDiagnostic::emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc,
DiagnosticsEngine::Level Level,
- ArrayRef<CharSourceRange> Ranges,
- const SourceManager &SM) {
+ ArrayRef<CharSourceRange> Ranges) {
if (PLoc.isInvalid()) {
// At least print the file name if available:
- FileID FID = SM.getFileID(Loc);
+ FileID FID = Loc.getFileID();
if (FID.isValid()) {
- const FileEntry* FE = SM.getFileEntryForID(FID);
+ const FileEntry *FE = Loc.getFileEntry();
if (FE && FE->isValid()) {
- emitFilename(FE->getName(), SM);
+ emitFilename(FE->getName(), Loc.getManager());
if (FE->isInPCH())
OS << " (in PCH)";
OS << ": ";
@@ -813,7 +808,7 @@ void TextDiagnostic::emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
if (DiagOpts->ShowColors)
OS.changeColor(savedColor, true);
- emitFilename(PLoc.getFilename(), SM);
+ emitFilename(PLoc.getFilename(), Loc.getManager());
switch (DiagOpts->getFormat()) {
case DiagnosticOptions::Clang: OS << ':' << LineNo; break;
case DiagnosticOptions::MSVC: OS << '(' << LineNo; break;
@@ -848,8 +843,7 @@ void TextDiagnostic::emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
}
if (DiagOpts->ShowSourceRanges && !Ranges.empty()) {
- FileID CaretFileID =
- SM.getFileID(SM.getExpansionLoc(Loc));
+ FileID CaretFileID = Loc.getExpansionLoc().getFileID();
bool PrintedRange = false;
for (ArrayRef<CharSourceRange>::const_iterator RI = Ranges.begin(),
@@ -858,8 +852,10 @@ void TextDiagnostic::emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
// Ignore invalid ranges.
if (!RI->isValid()) continue;
- SourceLocation B = SM.getExpansionLoc(RI->getBegin());
- SourceLocation E = SM.getExpansionLoc(RI->getEnd());
+ FullSourceLoc B =
+ FullSourceLoc(RI->getBegin(), Loc.getManager()).getExpansionLoc();
+ FullSourceLoc E =
+ FullSourceLoc(RI->getEnd(), Loc.getManager()).getExpansionLoc();
// If the End location and the start location are the same and are a
// macro location, then the range was something that came from a
@@ -867,10 +863,12 @@ void TextDiagnostic::emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
// best we can do is to highlight the range. If this is a
// function-like macro, we'd also like to highlight the arguments.
if (B == E && RI->getEnd().isMacroID())
- E = SM.getExpansionRange(RI->getEnd()).second;
+ E = FullSourceLoc(RI->getEnd(), Loc.getManager())
+ .getExpansionRange()
+ .second;
- std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(B);
- std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(E);
+ std::pair<FileID, unsigned> BInfo = B.getDecomposedLoc();
+ std::pair<FileID, unsigned> EInfo = E.getDecomposedLoc();
// If the start or end of the range is in another file, just discard
// it.
@@ -881,13 +879,10 @@ void TextDiagnostic::emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
// tokens.
unsigned TokSize = 0;
if (RI->isTokenRange())
- TokSize = Lexer::MeasureTokenLength(E, SM, LangOpts);
+ TokSize = Lexer::MeasureTokenLength(E, E.getManager(), LangOpts);
- OS << '{' << SM.getLineNumber(BInfo.first, BInfo.second) << ':'
- << SM.getColumnNumber(BInfo.first, BInfo.second) << '-'
- << SM.getLineNumber(EInfo.first, EInfo.second) << ':'
- << (SM.getColumnNumber(EInfo.first, EInfo.second)+TokSize)
- << '}';
+ OS << '{' << B.getLineNumber() << ':' << B.getColumnNumber() << '-'
+ << E.getLineNumber() << ':' << (E.getColumnNumber() + TokSize) << '}';
PrintedRange = true;
}
@@ -897,9 +892,7 @@ void TextDiagnostic::emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
OS << ' ';
}
-void TextDiagnostic::emitIncludeLocation(SourceLocation Loc,
- PresumedLoc PLoc,
- const SourceManager &SM) {
+void TextDiagnostic::emitIncludeLocation(FullSourceLoc Loc, PresumedLoc PLoc) {
if (DiagOpts->ShowLocation && PLoc.isValid())
OS << "In file included from " << PLoc.getFilename() << ':'
<< PLoc.getLine() << ":\n";
@@ -907,9 +900,8 @@ void TextDiagnostic::emitIncludeLocation(SourceLocation Loc,
OS << "In included file:\n";
}
-void TextDiagnostic::emitImportLocation(SourceLocation Loc, PresumedLoc PLoc,
- StringRef ModuleName,
- const SourceManager &SM) {
+void TextDiagnostic::emitImportLocation(FullSourceLoc Loc, PresumedLoc PLoc,
+ StringRef ModuleName) {
if (DiagOpts->ShowLocation && PLoc.isValid())
OS << "In module '" << ModuleName << "' imported from "
<< PLoc.getFilename() << ':' << PLoc.getLine() << ":\n";
@@ -917,10 +909,9 @@ void TextDiagnostic::emitImportLocation(SourceLocation Loc, PresumedLoc PLoc,
OS << "In module '" << ModuleName << "':\n";
}
-void TextDiagnostic::emitBuildingModuleLocation(SourceLocation Loc,
+void TextDiagnostic::emitBuildingModuleLocation(FullSourceLoc Loc,
PresumedLoc PLoc,
- StringRef ModuleName,
- const SourceManager &SM) {
+ StringRef ModuleName) {
if (DiagOpts->ShowLocation && PLoc.isValid())
OS << "While building module '" << ModuleName << "' imported from "
<< PLoc.getFilename() << ':' << PLoc.getLine() << ":\n";
@@ -1134,10 +1125,8 @@ static std::string buildFixItInsertionLine(unsigned LineNo,
/// \param Ranges The underlined ranges for this code snippet.
/// \param Hints The FixIt hints active for this diagnostic.
void TextDiagnostic::emitSnippetAndCaret(
- SourceLocation Loc, DiagnosticsEngine::Level Level,
- SmallVectorImpl<CharSourceRange>& Ranges,
- ArrayRef<FixItHint> Hints,
- const SourceManager &SM) {
+ FullSourceLoc Loc, DiagnosticsEngine::Level Level,
+ SmallVectorImpl<CharSourceRange> &Ranges, ArrayRef<FixItHint> Hints) {
assert(Loc.isValid() && "must have a valid source location here");
assert(Loc.isFileID() && "must have a file location here");
@@ -1154,18 +1143,18 @@ void TextDiagnostic::emitSnippetAndCaret(
return;
// Decompose the location into a FID/Offset pair.
- std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
+ std::pair<FileID, unsigned> LocInfo = Loc.getDecomposedLoc();
FileID FID = LocInfo.first;
- unsigned CaretFileOffset = LocInfo.second;
+ const SourceManager &SM = Loc.getManager();
// Get information about the buffer it points into.
bool Invalid = false;
- StringRef BufData = SM.getBufferData(FID, &Invalid);
+ StringRef BufData = Loc.getBufferData(&Invalid);
if (Invalid)
return;
- unsigned CaretLineNo = SM.getLineNumber(FID, CaretFileOffset);
- unsigned CaretColNo = SM.getColumnNumber(FID, CaretFileOffset);
+ unsigned CaretLineNo = Loc.getLineNumber();
+ unsigned CaretColNo = Loc.getColumnNumber();
// Arbitrarily stop showing snippets when the line is too long.
static const size_t MaxLineLengthToPrint = 4096;
diff --git a/lib/Frontend/TextDiagnosticPrinter.cpp b/lib/Frontend/TextDiagnosticPrinter.cpp
index 17646b48e23d..5dd3252d5b1e 100644
--- a/lib/Frontend/TextDiagnosticPrinter.cpp
+++ b/lib/Frontend/TextDiagnosticPrinter.cpp
@@ -150,10 +150,9 @@ void TextDiagnosticPrinter::HandleDiagnostic(DiagnosticsEngine::Level Level,
"Unexpected diagnostic with no source manager");
assert(TextDiag && "Unexpected diagnostic outside source file processing");
- TextDiag->emitDiagnostic(Info.getLocation(), Level, DiagMessageStream.str(),
- Info.getRanges(),
- Info.getFixItHints(),
- &Info.getSourceManager());
+ TextDiag->emitDiagnostic(
+ FullSourceLoc(Info.getLocation(), Info.getSourceManager()), Level,
+ DiagMessageStream.str(), Info.getRanges(), Info.getFixItHints());
OS.flush();
}
diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp
index 018d59e5e871..40f78ce25ceb 100644
--- a/lib/Lex/ModuleMap.cpp
+++ b/lib/Lex/ModuleMap.cpp
@@ -2710,7 +2710,8 @@ bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem,
// If the module map file wasn't already entered, do so now.
if (ID.isInvalid()) {
- auto FileCharacter = IsSystem ? SrcMgr::C_System : SrcMgr::C_User;
+ auto FileCharacter =
+ IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap;
ID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter);
}
diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp
index a6bfc32e2213..8af9a50cc204 100644
--- a/lib/Lex/PPMacroExpansion.cpp
+++ b/lib/Lex/PPMacroExpansion.cpp
@@ -1315,6 +1315,8 @@ static bool HasExtension(const Preprocessor &PP, StringRef Extension) {
.Case("cxx_binary_literals", true)
.Case("cxx_init_captures", LangOpts.CPlusPlus11)
.Case("cxx_variable_templates", LangOpts.CPlusPlus)
+ // Miscellaneous language extensions
+ .Case("overloadable_unmarked", true)
.Default(false);
}
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index d0ce9fc89583..07054546f42f 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -71,11 +71,18 @@ TypeResult Parser::ParseTypeName(SourceRange *Range,
return Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
}
+/// \brief Normalizes an attribute name by dropping prefixed and suffixed __.
+static StringRef normalizeAttrName(StringRef Name) {
+ if (Name.size() >= 4 && Name.startswith("__") && Name.endswith("__"))
+ return Name.drop_front(2).drop_back(2);
+ return Name;
+}
+
/// isAttributeLateParsed - Return true if the attribute has arguments that
/// require late parsing.
static bool isAttributeLateParsed(const IdentifierInfo &II) {
#define CLANG_ATTR_LATE_PARSED_LIST
- return llvm::StringSwitch<bool>(II.getName())
+ return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))
#include "clang/Parse/AttrParserStringSwitches.inc"
.Default(false);
#undef CLANG_ATTR_LATE_PARSED_LIST
@@ -200,13 +207,6 @@ void Parser::ParseGNUAttributes(ParsedAttributes &attrs,
}
}
-/// \brief Normalizes an attribute name by dropping prefixed and suffixed __.
-static StringRef normalizeAttrName(StringRef Name) {
- if (Name.size() >= 4 && Name.startswith("__") && Name.endswith("__"))
- Name = Name.drop_front(2).drop_back(2);
- return Name;
-}
-
/// \brief Determine whether the given attribute has an identifier argument.
static bool attributeHasIdentifierArg(const IdentifierInfo &II) {
#define CLANG_ATTR_IDENTIFIER_ARG_LIST
@@ -4319,8 +4319,15 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
return;
}
- if (Tok.is(tok::l_brace) && TUK != Sema::TUK_Reference)
- ParseEnumBody(StartLoc, TagDecl);
+ if (Tok.is(tok::l_brace) && TUK != Sema::TUK_Reference) {
+ Decl *D = SkipBody.CheckSameAsPrevious ? SkipBody.New : TagDecl;
+ ParseEnumBody(StartLoc, D);
+ if (SkipBody.CheckSameAsPrevious &&
+ !Actions.ActOnDuplicateDefinition(DS, TagDecl, SkipBody)) {
+ DS.SetTypeSpecError();
+ return;
+ }
+ }
if (DS.SetTypeSpecType(DeclSpec::TST_enum, StartLoc,
NameLoc.isValid() ? NameLoc : StartLoc,
@@ -4392,11 +4399,9 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) {
}
// Install the enumerator constant into EnumDecl.
- Decl *EnumConstDecl = Actions.ActOnEnumConstant(getCurScope(), EnumDecl,
- LastEnumConstDecl,
- IdentLoc, Ident,
- attrs.getList(), EqualLoc,
- AssignedVal.get());
+ Decl *EnumConstDecl = Actions.ActOnEnumConstant(
+ getCurScope(), EnumDecl, LastEnumConstDecl, IdentLoc, Ident,
+ attrs.getList(), EqualLoc, AssignedVal.get());
EnumAvailabilityDiags.back().done();
EnumConstantDecls.push_back(EnumConstDecl);
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index a724fa242268..2301284b7f43 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -1910,12 +1910,22 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
else if (getLangOpts().CPlusPlus)
ParseCXXMemberSpecification(StartLoc, AttrFixitLoc, attrs, TagType,
TagOrTempResult.get());
- else
- ParseStructUnionBody(StartLoc, TagType, TagOrTempResult.get());
+ else {
+ Decl *D =
+ SkipBody.CheckSameAsPrevious ? SkipBody.New : TagOrTempResult.get();
+ // Parse the definition body.
+ ParseStructUnionBody(StartLoc, TagType, D);
+ if (SkipBody.CheckSameAsPrevious &&
+ !Actions.ActOnDuplicateDefinition(DS, TagOrTempResult.get(),
+ SkipBody)) {
+ DS.SetTypeSpecError();
+ return;
+ }
+ }
}
if (!TagOrTempResult.isInvalid())
- // Delayed proccessing of attributes.
+ // Delayed processing of attributes.
Actions.ProcessDeclAttributeDelayed(TagOrTempResult.get(), attrs.getList());
const char *PrevSpec = nullptr;
diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp
index 934e13e72d05..fd2d07957c2b 100644
--- a/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/lib/Sema/AnalysisBasedWarnings.cpp
@@ -305,10 +305,14 @@ static bool isThrowCaught(const CXXThrowExpr *Throw,
CaughtType = CaughtType->castAs<ReferenceType>()
->getPointeeType()
->getUnqualifiedDesugaredType();
+ if (ThrowType->isPointerType() && CaughtType->isPointerType()) {
+ ThrowType = ThrowType->getPointeeType()->getUnqualifiedDesugaredType();
+ CaughtType = CaughtType->getPointeeType()->getUnqualifiedDesugaredType();
+ }
if (CaughtType == ThrowType)
return true;
const CXXRecordDecl *CaughtAsRecordType =
- CaughtType->getPointeeCXXRecordDecl();
+ CaughtType->getAsCXXRecordDecl();
const CXXRecordDecl *ThrowTypeAsRecordType = ThrowType->getAsCXXRecordDecl();
if (CaughtAsRecordType && ThrowTypeAsRecordType)
return ThrowTypeAsRecordType->isDerivedFrom(CaughtAsRecordType);
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index 007a5e483e6c..34f5e26be810 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -1688,7 +1688,8 @@ bool Sema::checkOpenCLDisabledTypeDeclSpec(const DeclSpec &DS, QualType QT) {
QT, OpenCLTypeExtMap);
}
-bool Sema::checkOpenCLDisabledDecl(const Decl &D, const Expr &E) {
- return checkOpenCLDisabledTypeOrDecl(&D, E.getLocStart(), "",
+bool Sema::checkOpenCLDisabledDecl(const NamedDecl &D, const Expr &E) {
+ IdentifierInfo *FnName = D.getIdentifier();
+ return checkOpenCLDisabledTypeOrDecl(&D, E.getLocStart(), FnName,
OpenCLDeclExtMap, 1, D.getSourceRange());
}
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index b794628db738..845c4bf61b7a 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -6000,6 +6000,7 @@ shouldNotPrintDirectly(const ASTContext &Context,
while (const TypedefType *UserTy = TyTy->getAs<TypedefType>()) {
StringRef Name = UserTy->getDecl()->getName();
QualType CastTy = llvm::StringSwitch<QualType>(Name)
+ .Case("CFIndex", Context.LongTy)
.Case("NSInteger", Context.LongTy)
.Case("NSUInteger", Context.UnsignedLongTy)
.Case("SInt32", Context.IntTy)
@@ -9935,6 +9936,28 @@ void Sema::CheckBoolLikeConversion(Expr *E, SourceLocation CC) {
::CheckBoolLikeConversion(*this, E, CC);
}
+/// Diagnose when expression is an integer constant expression and its evaluation
+/// results in integer overflow
+void Sema::CheckForIntOverflow (Expr *E) {
+ // Use a work list to deal with nested struct initializers.
+ SmallVector<Expr *, 2> Exprs(1, E);
+
+ do {
+ Expr *E = Exprs.pop_back_val();
+
+ if (isa<BinaryOperator>(E->IgnoreParenCasts())) {
+ E->IgnoreParenCasts()->EvaluateForOverflow(Context);
+ continue;
+ }
+
+ if (auto InitList = dyn_cast<InitListExpr>(E))
+ Exprs.append(InitList->inits().begin(), InitList->inits().end());
+
+ if (isa<ObjCBoxedExpr>(E))
+ E->IgnoreParenCasts()->EvaluateForOverflow(Context);
+ } while (!Exprs.empty());
+}
+
namespace {
/// \brief Visitor for expressions which looks for unsequenced operations on the
/// same object.
@@ -10436,7 +10459,7 @@ void Sema::CheckCompletedExpr(Expr *E, SourceLocation CheckLoc,
if (!E->isInstantiationDependent())
CheckUnsequencedOperations(E);
if (!IsConstexpr && !E->isValueDependent())
- E->EvaluateForOverflow(Context);
+ CheckForIntOverflow(E);
DiagnoseMisalignedMembers();
}
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index e340456bc6da..ef8a408f90de 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -1327,15 +1327,17 @@ void Sema::ActOnExitFunctionContext() {
/// overloaded function declaration or has the "overloadable"
/// attribute.
static bool AllowOverloadingOfFunction(LookupResult &Previous,
- ASTContext &Context) {
+ ASTContext &Context,
+ const FunctionDecl *New) {
if (Context.getLangOpts().CPlusPlus)
return true;
if (Previous.getResultKind() == LookupResult::FoundOverloaded)
return true;
- return (Previous.getResultKind() == LookupResult::Found
- && Previous.getFoundDecl()->hasAttr<OverloadableAttr>());
+ return Previous.getResultKind() == LookupResult::Found &&
+ (Previous.getFoundDecl()->hasAttr<OverloadableAttr>() ||
+ New->hasAttr<OverloadableAttr>());
}
/// Add this decl to the scope shadowed decl chains.
@@ -2933,6 +2935,41 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD,
New->dropAttr<InternalLinkageAttr>();
}
+ if (!getLangOpts().CPlusPlus) {
+ bool OldOvl = Old->hasAttr<OverloadableAttr>();
+ if (OldOvl != New->hasAttr<OverloadableAttr>() && !Old->isImplicit()) {
+ Diag(New->getLocation(), diag::err_attribute_overloadable_mismatch)
+ << New << OldOvl;
+
+ // Try our best to find a decl that actually has the overloadable
+ // attribute for the note. In most cases (e.g. programs with only one
+ // broken declaration/definition), this won't matter.
+ //
+ // FIXME: We could do this if we juggled some extra state in
+ // OverloadableAttr, rather than just removing it.
+ const Decl *DiagOld = Old;
+ if (OldOvl) {
+ auto OldIter = llvm::find_if(Old->redecls(), [](const Decl *D) {
+ const auto *A = D->getAttr<OverloadableAttr>();
+ return A && !A->isImplicit();
+ });
+ // If we've implicitly added *all* of the overloadable attrs to this
+ // chain, emitting a "previous redecl" note is pointless.
+ DiagOld = OldIter == Old->redecls_end() ? nullptr : *OldIter;
+ }
+
+ if (DiagOld)
+ Diag(DiagOld->getLocation(),
+ diag::note_attribute_overloadable_prev_overload)
+ << OldOvl;
+
+ if (OldOvl)
+ New->addAttr(OverloadableAttr::CreateImplicit(Context));
+ else
+ New->dropAttr<OverloadableAttr>();
+ }
+ }
+
// If a function is first declared with a calling convention, but is later
// declared or defined without one, all following decls assume the calling
// convention of the first.
@@ -9179,6 +9216,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
bool Redeclaration = false;
NamedDecl *OldDecl = nullptr;
+ bool MayNeedOverloadableChecks = false;
// Merge or overload the declaration with an existing declaration of
// the same name, if appropriate.
@@ -9187,13 +9225,14 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
// a declaration that requires merging. If it's an overload,
// there's no more work to do here; we'll just add the new
// function to the scope.
- if (!AllowOverloadingOfFunction(Previous, Context)) {
+ if (!AllowOverloadingOfFunction(Previous, Context, NewFD)) {
NamedDecl *Candidate = Previous.getRepresentativeDecl();
if (shouldLinkPossiblyHiddenDecl(Candidate, NewFD)) {
Redeclaration = true;
OldDecl = Candidate;
}
} else {
+ MayNeedOverloadableChecks = true;
switch (CheckOverload(S, NewFD, Previous, OldDecl,
/*NewIsUsingDecl*/ false)) {
case Ovl_Match:
@@ -9208,18 +9247,6 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
Redeclaration = false;
break;
}
-
- if (!getLangOpts().CPlusPlus && !NewFD->hasAttr<OverloadableAttr>()) {
- // If a function name is overloadable in C, then every function
- // with that name must be marked "overloadable".
- Diag(NewFD->getLocation(), diag::err_attribute_overloadable_missing)
- << Redeclaration << NewFD;
- NamedDecl *OverloadedDecl =
- Redeclaration ? OldDecl : Previous.getRepresentativeDecl();
- Diag(OverloadedDecl->getLocation(),
- diag::note_attribute_overloadable_prev_overload);
- NewFD->addAttr(OverloadableAttr::CreateImplicit(Context));
- }
}
}
@@ -9234,15 +9261,10 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
MergeTypeWithPrevious = false;
// ... except in the presence of __attribute__((overloadable)).
- if (OldDecl->hasAttr<OverloadableAttr>()) {
- if (!getLangOpts().CPlusPlus && !NewFD->hasAttr<OverloadableAttr>()) {
- Diag(NewFD->getLocation(), diag::err_attribute_overloadable_missing)
- << Redeclaration << NewFD;
- Diag(Previous.getFoundDecl()->getLocation(),
- diag::note_attribute_overloadable_prev_overload);
- NewFD->addAttr(OverloadableAttr::CreateImplicit(Context));
- }
+ if (OldDecl->hasAttr<OverloadableAttr>() ||
+ NewFD->hasAttr<OverloadableAttr>()) {
if (IsOverload(NewFD, cast<FunctionDecl>(OldDecl), false)) {
+ MayNeedOverloadableChecks = true;
Redeclaration = false;
OldDecl = nullptr;
}
@@ -9337,6 +9359,29 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
NewFD->setAccess(OldDecl->getAccess());
}
}
+ } else if (!getLangOpts().CPlusPlus && MayNeedOverloadableChecks &&
+ !NewFD->getAttr<OverloadableAttr>()) {
+ assert((Previous.empty() ||
+ llvm::any_of(Previous,
+ [](const NamedDecl *ND) {
+ return ND->hasAttr<OverloadableAttr>();
+ })) &&
+ "Non-redecls shouldn't happen without overloadable present");
+
+ auto OtherUnmarkedIter = llvm::find_if(Previous, [](const NamedDecl *ND) {
+ const auto *FD = dyn_cast<FunctionDecl>(ND);
+ return FD && !FD->hasAttr<OverloadableAttr>();
+ });
+
+ if (OtherUnmarkedIter != Previous.end()) {
+ Diag(NewFD->getLocation(),
+ diag::err_attribute_overloadable_multiple_unmarked_overloads);
+ Diag((*OtherUnmarkedIter)->getLocation(),
+ diag::note_attribute_overloadable_prev_overload)
+ << false;
+
+ NewFD->addAttr(OverloadableAttr::CreateImplicit(Context));
+ }
}
// Semantic checking for this function declaration (in isolation).
@@ -11100,9 +11145,7 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
bool IsGlobal = GlobalStorage && !var->isStaticLocal();
QualType baseType = Context.getBaseElementType(type);
- if (!var->getDeclContext()->isDependentContext() &&
- Init && !Init->isValueDependent()) {
-
+ if (Init && !Init->isValueDependent()) {
if (var->isConstexpr()) {
SmallVector<PartialDiagnosticAt, 8> Notes;
if (!var->evaluateValue(Notes) || !var->isInitICE()) {
@@ -11932,7 +11975,7 @@ Sema::CheckForFunctionRedefinition(FunctionDecl *FD,
if (canRedefineFunction(Definition, getLangOpts()))
return;
- // Don't emit an error when this is redifinition of a typo-corrected
+ // Don't emit an error when this is redefinition of a typo-corrected
// definition.
if (TypoCorrectedFunctionDefinitions.count(Definition))
return;
@@ -13190,6 +13233,55 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
if (TUK == TUK_Friend || TUK == TUK_Reference)
Redecl = NotForRedeclaration;
+ /// Create a new tag decl in C/ObjC. Since the ODR-like semantics for ObjC/C
+ /// implemented asks for structural equivalence checking, the returned decl
+ /// here is passed back to the parser, allowing the tag body to be parsed.
+ auto createTagFromNewDecl = [&]() -> TagDecl * {
+ assert(!getLangOpts().CPlusPlus && "not meant for C++ usage");
+ // If there is an identifier, use the location of the identifier as the
+ // location of the decl, otherwise use the location of the struct/union
+ // keyword.
+ SourceLocation Loc = NameLoc.isValid() ? NameLoc : KWLoc;
+ TagDecl *New = nullptr;
+
+ if (Kind == TTK_Enum) {
+ New = EnumDecl::Create(Context, SearchDC, KWLoc, Loc, Name, nullptr,
+ ScopedEnum, ScopedEnumUsesClassTag,
+ !EnumUnderlying.isNull());
+ // If this is an undefined enum, bail.
+ if (TUK != TUK_Definition && !Invalid)
+ return nullptr;
+ if (EnumUnderlying) {
+ EnumDecl *ED = cast<EnumDecl>(New);
+ if (TypeSourceInfo *TI = EnumUnderlying.dyn_cast<TypeSourceInfo *>())
+ ED->setIntegerTypeSourceInfo(TI);
+ else
+ ED->setIntegerType(QualType(EnumUnderlying.get<const Type *>(), 0));
+ ED->setPromotionType(ED->getIntegerType());
+ }
+ } else { // struct/union
+ New = RecordDecl::Create(Context, Kind, SearchDC, KWLoc, Loc, Name,
+ nullptr);
+ }
+
+ if (RecordDecl *RD = dyn_cast<RecordDecl>(New)) {
+ // Add alignment attributes if necessary; these attributes are checked
+ // when the ASTContext lays out the structure.
+ //
+ // It is important for implementing the correct semantics that this
+ // happen here (in ActOnTag). The #pragma pack stack is
+ // maintained as a result of parser callbacks which can occur at
+ // many points during the parsing of a struct declaration (because
+ // the #pragma tokens are effectively skipped over during the
+ // parsing of the struct).
+ if (TUK == TUK_Definition) {
+ AddAlignmentAttributesForRecord(RD);
+ AddMsStructLayoutForRecord(RD);
+ }
+ }
+ return New;
+ };
+
LookupResult Previous(*this, Name, NameLoc, LookupTagName, Redecl);
if (Name && SS.isNotEmpty()) {
// We have a nested-name tag ('struct foo::bar').
@@ -13595,16 +13687,28 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
TSK_ExplicitSpecialization;
}
+ // Note that clang allows ODR-like semantics for ObjC/C, i.e., do
+ // not keep more that one definition around (merge them). However,
+ // ensure the decl passes the structural compatibility check in
+ // C11 6.2.7/1 (or 6.1.2.6/1 in C89).
NamedDecl *Hidden = nullptr;
- if (SkipBody && getLangOpts().CPlusPlus &&
- !hasVisibleDefinition(Def, &Hidden)) {
+ if (SkipBody && !hasVisibleDefinition(Def, &Hidden)) {
// There is a definition of this tag, but it is not visible. We
// explicitly make use of C++'s one definition rule here, and
// assume that this definition is identical to the hidden one
// we already have. Make the existing definition visible and
// use it in place of this one.
- SkipBody->ShouldSkip = true;
- makeMergedDefinitionVisible(Hidden);
+ if (!getLangOpts().CPlusPlus) {
+ // Postpone making the old definition visible until after we
+ // complete parsing the new one and do the structural
+ // comparison.
+ SkipBody->CheckSameAsPrevious = true;
+ SkipBody->New = createTagFromNewDecl();
+ SkipBody->Previous = Hidden;
+ } else {
+ SkipBody->ShouldSkip = true;
+ makeMergedDefinitionVisible(Hidden);
+ }
return Def;
} else if (!IsExplicitSpecializationAfterInstantiation) {
// A redeclaration in function prototype scope in C isn't
@@ -13832,7 +13936,7 @@ CreateNewDecl:
// the ASTContext lays out the structure.
//
// It is important for implementing the correct semantics that this
- // happen here (in act on tag decl). The #pragma pack stack is
+ // happen here (in ActOnTag). The #pragma pack stack is
// maintained as a result of parser callbacks which can occur at
// many points during the parsing of a struct declaration (because
// the #pragma tokens are effectively skipped over during the
@@ -13968,6 +14072,16 @@ void Sema::ActOnTagStartDefinition(Scope *S, Decl *TagD) {
AddPushedVisibilityAttribute(Tag);
}
+bool Sema::ActOnDuplicateDefinition(DeclSpec &DS, Decl *Prev,
+ SkipBodyInfo &SkipBody) {
+ if (!hasStructuralCompatLayout(Prev, SkipBody.New))
+ return false;
+
+ // Make the previous decl visible.
+ makeMergedDefinitionVisible(SkipBody.Previous);
+ return true;
+}
+
Decl *Sema::ActOnObjCContainerStartDefinition(Decl *IDecl) {
assert(isa<ObjCContainerDecl>(IDecl) &&
"ActOnObjCContainerStartDefinition - Not ObjCContainerDecl");
@@ -15389,7 +15503,7 @@ Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst,
// different from T:
// - every enumerator of every member of class T that is an unscoped
// enumerated type
- if (!TheEnumDecl->isScoped())
+ if (getLangOpts().CPlusPlus && !TheEnumDecl->isScoped())
DiagnoseClassNameShadow(TheEnumDecl->getDeclContext(),
DeclarationNameInfo(Id, IdLoc));
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index e8503427536d..1929bc539188 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -6571,7 +6571,7 @@ void Sema::ProcessDeclAttributeList(Scope *S, Decl *D,
}
}
-// Helper for delayed proccessing TransparentUnion attribute.
+// Helper for delayed processing TransparentUnion attribute.
void Sema::ProcessDeclAttributeDelayed(Decl *D, const AttributeList *AttrList) {
for (const AttributeList *Attr = AttrList; Attr; Attr = Attr->getNext())
if (Attr->getKind() == AttributeList::AT_TransparentUnion) {
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 453ece9d9c4d..e9070881afe4 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -3778,6 +3778,15 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
if (BaseType.isNull())
return true;
+ TInfo = Context.CreateTypeSourceInfo(BaseType);
+ DependentNameTypeLoc TL =
+ TInfo->getTypeLoc().castAs<DependentNameTypeLoc>();
+ if (!TL.isNull()) {
+ TL.setNameLoc(IdLoc);
+ TL.setElaboratedKeywordLoc(SourceLocation());
+ TL.setQualifierLoc(SS.getWithLocInContext(Context));
+ }
+
R.clear();
R.setLookupName(MemberOrBase);
}
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 710ead30790f..a9cf3ec7990b 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -1646,6 +1646,27 @@ static bool isLegalArrayNewInitializer(CXXNewExpr::InitializationStyle Style,
return false;
}
+// Emit a diagnostic if an aligned allocation/deallocation function that is not
+// implemented in the standard library is selected.
+static void diagnoseUnavailableAlignedAllocation(const FunctionDecl &FD,
+ SourceLocation Loc, bool IsDelete,
+ Sema &S) {
+ if (!S.getLangOpts().AlignedAllocationUnavailable)
+ return;
+
+ // Return if there is a definition.
+ if (FD.isDefined())
+ return;
+
+ bool IsAligned = false;
+ if (FD.isReplaceableGlobalAllocationFunction(&IsAligned) && IsAligned) {
+ S.Diag(Loc, diag::warn_aligned_allocation_unavailable)
+ << IsDelete << FD.getType().getAsString()
+ << S.getASTContext().getTargetInfo().getTriple().str();
+ S.Diag(Loc, diag::note_silence_unligned_allocation_unavailable);
+ }
+}
+
ExprResult
Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
SourceLocation PlacementLParen,
@@ -2023,11 +2044,13 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
if (DiagnoseUseOfDecl(OperatorNew, StartLoc))
return ExprError();
MarkFunctionReferenced(StartLoc, OperatorNew);
+ diagnoseUnavailableAlignedAllocation(*OperatorNew, StartLoc, false, *this);
}
if (OperatorDelete) {
if (DiagnoseUseOfDecl(OperatorDelete, StartLoc))
return ExprError();
MarkFunctionReferenced(StartLoc, OperatorDelete);
+ diagnoseUnavailableAlignedAllocation(*OperatorDelete, StartLoc, true, *this);
}
// C++0x [expr.new]p17:
@@ -3243,6 +3266,9 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
PDiag(diag::err_access_dtor) << PointeeElem);
}
}
+
+ diagnoseUnavailableAlignedAllocation(*OperatorDelete, StartLoc, true,
+ *this);
}
CXXDeleteExpr *Result = new (Context) CXXDeleteExpr(
@@ -4093,15 +4119,9 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT,
case UTT_IsStandardLayout:
case UTT_IsPOD:
case UTT_IsLiteral:
- ArgTy = QualType(ArgTy->getBaseElementTypeUnsafe(), 0);
- LLVM_FALLTHROUGH;
-
- // C++1z [meta.unary.prop]:
- // T shall be a complete type, cv void, or an array of unknown bound.
- case UTT_IsDestructible:
- case UTT_IsNothrowDestructible:
- case UTT_IsTriviallyDestructible:
- // Per the GCC type traits documentation, the same constraints apply to these.
+ // Per the GCC type traits documentation, T shall be a complete type, cv void,
+ // or an array of unknown bound. But GCC actually imposes the same constraints
+ // as above.
case UTT_HasNothrowAssign:
case UTT_HasNothrowMoveAssign:
case UTT_HasNothrowConstructor:
@@ -4113,6 +4133,14 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT,
case UTT_HasTrivialCopy:
case UTT_HasTrivialDestructor:
case UTT_HasVirtualDestructor:
+ ArgTy = QualType(ArgTy->getBaseElementTypeUnsafe(), 0);
+ LLVM_FALLTHROUGH;
+
+ // C++1z [meta.unary.prop]:
+ // T shall be a complete type, cv void, or an array of unknown bound.
+ case UTT_IsDestructible:
+ case UTT_IsNothrowDestructible:
+ case UTT_IsTriviallyDestructible:
if (ArgTy->isIncompleteArrayType() || ArgTy->isVoidType())
return true;
diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp
index 2b7733d2adbd..49da0e499771 100644
--- a/lib/Sema/SemaOpenMP.cpp
+++ b/lib/Sema/SemaOpenMP.cpp
@@ -412,6 +412,30 @@ public:
return false;
}
+ /// Do the check specified in \a Check to all component lists at a given level
+ /// and return true if any issue is found.
+ bool checkMappableExprComponentListsForDeclAtLevel(
+ ValueDecl *VD, unsigned Level,
+ const llvm::function_ref<
+ bool(OMPClauseMappableExprCommon::MappableExprComponentListRef,
+ OpenMPClauseKind)> &Check) {
+ if (isStackEmpty())
+ return false;
+
+ auto StartI = Stack.back().first.begin();
+ auto EndI = Stack.back().first.end();
+ if (std::distance(StartI, EndI) <= (int)Level)
+ return false;
+ std::advance(StartI, Level);
+
+ auto MI = StartI->MappedExprComponents.find(VD);
+ if (MI != StartI->MappedExprComponents.end())
+ for (auto &L : MI->second.Components)
+ if (Check(L, MI->second.Kind))
+ return true;
+ return false;
+ }
+
/// Create a new mappable expression component list associated with a given
/// declaration and initialize it with the provided list of components.
void addMappableExpressionComponents(
@@ -994,9 +1018,8 @@ bool Sema::IsOpenMPCapturedByRef(ValueDecl *D, unsigned Level) {
bool IsVariableUsedInMapClause = false;
bool IsVariableAssociatedWithSection = false;
- DSAStack->checkMappableExprComponentListsForDecl(
- D, /*CurrentRegionOnly=*/true,
- [&](OMPClauseMappableExprCommon::MappableExprComponentListRef
+ DSAStack->checkMappableExprComponentListsForDeclAtLevel(
+ D, Level, [&](OMPClauseMappableExprCommon::MappableExprComponentListRef
MapExprComponents,
OpenMPClauseKind WhereFoundClauseKind) {
// Only the map clause information influences how a variable is
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 8c8402e75e37..b19dcb2a5099 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -15,6 +15,7 @@
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTMutationListener.h"
+#include "clang/AST/ASTStructuralEquivalence.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
@@ -7111,6 +7112,20 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
return false;
}
+bool Sema::hasStructuralCompatLayout(Decl *D, Decl *Suggested) {
+ llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls;
+ if (!Suggested)
+ return false;
+
+ // FIXME: Add a specific mode for C11 6.2.7/1 in StructuralEquivalenceContext
+ // and isolate from other C++ specific checks.
+ StructuralEquivalenceContext Ctx(
+ D->getASTContext(), Suggested->getASTContext(), NonEquivalentDecls,
+ false /*StrictTypeSpelling*/, true /*Complain*/,
+ true /*ErrorOnTagTypeMismatch*/);
+ return Ctx.IsStructurallyEquivalent(D, Suggested);
+}
+
/// \brief Determine whether there is any declaration of \p D that was ever a
/// definition (perhaps before module merging) and is currently visible.
/// \param D The definition of the entity.
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index ef2841849ff6..3aee3c04001d 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -856,7 +856,7 @@ static bool isInterestingIdentifier(ASTReader &Reader, IdentifierInfo &II,
II.isPoisoned() ||
(IsModule ? II.hasRevertedBuiltin() : II.getObjCOrBuiltinID()) ||
II.hasRevertedTokenIDToIdentifier() ||
- (!(IsModule && Reader.getContext().getLangOpts().CPlusPlus) &&
+ (!(IsModule && Reader.getPreprocessor().getLangOpts().CPlusPlus) &&
II.getFETokenInfo<void>());
}
@@ -1148,7 +1148,7 @@ bool ASTReader::ReadVisibleDeclContextStorage(ModuleFile &M,
void ASTReader::Error(StringRef Msg) const {
Error(diag::err_fe_pch_malformed, Msg);
- if (Context.getLangOpts().Modules && !Diags.isDiagnosticInFlight() &&
+ if (PP.getLangOpts().Modules && !Diags.isDiagnosticInFlight() &&
!PP.getHeaderSearchInfo().getModuleCachePath().empty()) {
Diag(diag::note_module_cache_path)
<< PP.getHeaderSearchInfo().getModuleCachePath();
@@ -1391,15 +1391,14 @@ bool ASTReader::ReadSLocEntry(int ID) {
const DeclID *FirstDecl = F->FileSortedDecls + Record[6];
unsigned NumFileDecls = Record[7];
- if (NumFileDecls) {
+ if (NumFileDecls && ContextObj) {
assert(F->FileSortedDecls && "FILE_SORTED_DECLS not encountered yet ?");
FileDeclIDs[FID] = FileDeclsInfo(F, llvm::makeArrayRef(FirstDecl,
NumFileDecls));
}
const SrcMgr::ContentCache *ContentCache
- = SourceMgr.getOrCreateContentCache(File,
- /*isSystemFile=*/FileCharacter != SrcMgr::C_User);
+ = SourceMgr.getOrCreateContentCache(File, isSystem(FileCharacter));
if (OverriddenBuffer && !ContentCache->BufferOverridden &&
ContentCache->ContentsEntry == ContentCache->OrigEntry &&
!ContentCache->getRawBuffer()) {
@@ -1697,9 +1696,9 @@ HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d,
HeaderFileInfo HFI;
unsigned Flags = *d++;
// FIXME: Refactor with mergeHeaderFileInfo in HeaderSearch.cpp.
- HFI.isImport |= (Flags >> 4) & 0x01;
- HFI.isPragmaOnce |= (Flags >> 3) & 0x01;
- HFI.DirInfo = (Flags >> 1) & 0x03;
+ HFI.isImport |= (Flags >> 5) & 0x01;
+ HFI.isPragmaOnce |= (Flags >> 4) & 0x01;
+ HFI.DirInfo = (Flags >> 1) & 0x07;
HFI.IndexHeaderMapHeader = Flags & 0x01;
// FIXME: Find a better way to handle this. Maybe just store a
// "has been included" flag?
@@ -2029,6 +2028,7 @@ ASTReader::readInputFileInfo(ModuleFile &F, unsigned ID) {
R.StoredTime = static_cast<time_t>(Record[2]);
R.Overridden = static_cast<bool>(Record[3]);
R.Transient = static_cast<bool>(Record[4]);
+ R.TopLevelModuleMap = static_cast<bool>(Record[5]);
R.Filename = Blob;
ResolveImportedPath(F, R.Filename);
return R;
@@ -2614,10 +2614,11 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
// contains any declarations lexically within it (which it always does!).
// This usually has no cost, since we very rarely need the lookup map for
// the translation unit outside C++.
- DeclContext *DC = Context.getTranslationUnitDecl();
- if (DC->hasExternalLexicalStorage() &&
- !getContext().getLangOpts().CPlusPlus)
- DC->setMustBuildLookupTable();
+ if (ASTContext *Ctx = ContextObj) {
+ DeclContext *DC = Ctx->getTranslationUnitDecl();
+ if (DC->hasExternalLexicalStorage() && !Ctx->getLangOpts().CPlusPlus)
+ DC->setMustBuildLookupTable();
+ }
return Success;
}
@@ -2706,7 +2707,33 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
// Read and process a record.
Record.clear();
StringRef Blob;
- switch ((ASTRecordTypes)Stream.readRecord(Entry.ID, Record, &Blob)) {
+ auto RecordType =
+ (ASTRecordTypes)Stream.readRecord(Entry.ID, Record, &Blob);
+
+ // If we're not loading an AST context, we don't care about most records.
+ if (!ContextObj) {
+ switch (RecordType) {
+ case IDENTIFIER_TABLE:
+ case IDENTIFIER_OFFSET:
+ case INTERESTING_IDENTIFIERS:
+ case STATISTICS:
+ case PP_CONDITIONAL_STACK:
+ case PP_COUNTER_VALUE:
+ case SOURCE_LOCATION_OFFSETS:
+ case MODULE_OFFSET_MAP:
+ case SOURCE_MANAGER_LINE_TABLE:
+ case SOURCE_LOCATION_PRELOADS:
+ case PPD_ENTITIES_OFFSETS:
+ case HEADER_SEARCH_TABLE:
+ case IMPORTED_MODULES:
+ case MACRO_OFFSET:
+ break;
+ default:
+ continue;
+ }
+ }
+
+ switch (RecordType) {
default: // Default behavior: ignore.
break;
@@ -2765,7 +2792,7 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
}
case TU_UPDATE_LEXICAL: {
- DeclContext *TU = Context.getTranslationUnitDecl();
+ DeclContext *TU = ContextObj->getTranslationUnitDecl();
LexicalContents Contents(
reinterpret_cast<const llvm::support::unaligned_uint32_t *>(
Blob.data()),
@@ -3455,12 +3482,6 @@ ASTReader::ReadModuleMapFileBlock(RecordData &Record, ModuleFile &F,
unsigned Idx = 0;
F.ModuleMapPath = ReadPath(F, Record, Idx);
- if (F.Kind == MK_ExplicitModule || F.Kind == MK_PrebuiltModule) {
- // For an explicitly-loaded module, we don't care whether the original
- // module map file exists or matches.
- return Success;
- }
-
// Try to resolve ModuleName in the current header search context and
// verify that it is found in the same module map file as we saved. If the
// top-level AST file is a main file, skip this check because there is no
@@ -3667,7 +3688,7 @@ bool ASTReader::loadGlobalIndex() {
return false;
if (TriedLoadingGlobalIndex || !UseGlobalIndex ||
- !Context.getLangOpts().Modules)
+ !PP.getLangOpts().Modules)
return true;
// Try to load the global index.
@@ -3685,7 +3706,7 @@ bool ASTReader::loadGlobalIndex() {
}
bool ASTReader::isGlobalIndexUnavailable() const {
- return Context.getLangOpts().Modules && UseGlobalIndex &&
+ return PP.getLangOpts().Modules && UseGlobalIndex &&
!hasGlobalIndex() && TriedLoadingGlobalIndex;
}
@@ -3743,7 +3764,9 @@ ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName,
Deserializing AnASTFile(this);
// Bump the generation number.
- unsigned PreviousGeneration = incrementGeneration(Context);
+ unsigned PreviousGeneration = 0;
+ if (ContextObj)
+ PreviousGeneration = incrementGeneration(*ContextObj);
unsigned NumModules = ModuleMgr.size();
SmallVector<ImportedModule, 4> Loaded;
@@ -3762,7 +3785,7 @@ ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName,
LoadedSet.insert(IM.Mod);
ModuleMgr.removeModules(ModuleMgr.begin() + NumModules, LoadedSet,
- Context.getLangOpts().Modules
+ PP.getLangOpts().Modules
? &PP.getHeaderSearchInfo().getModuleMap()
: nullptr);
@@ -3858,7 +3881,7 @@ ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName,
F.ImportLoc = TranslateSourceLocation(*M->ImportedBy, M->ImportLoc);
}
- if (!Context.getLangOpts().CPlusPlus ||
+ if (!PP.getLangOpts().CPlusPlus ||
(Type != MK_ImplicitModule && Type != MK_ExplicitModule &&
Type != MK_PrebuiltModule)) {
// Mark all of the identifiers in the identifier table as being out of date,
@@ -3915,7 +3938,8 @@ ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName,
// Might be unnecessary as use declarations are only used to build the
// module itself.
- InitializeContext();
+ if (ContextObj)
+ InitializeContext();
if (SemaObj)
UpdateSema();
@@ -3937,10 +3961,12 @@ ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName,
// For any Objective-C class definitions we have already loaded, make sure
// that we load any additional categories.
- for (unsigned I = 0, N = ObjCClassesLoaded.size(); I != N; ++I) {
- loadObjCCategories(ObjCClassesLoaded[I]->getGlobalID(),
- ObjCClassesLoaded[I],
- PreviousGeneration);
+ if (ContextObj) {
+ for (unsigned I = 0, N = ObjCClassesLoaded.size(); I != N; ++I) {
+ loadObjCCategories(ObjCClassesLoaded[I]->getGlobalID(),
+ ObjCClassesLoaded[I],
+ PreviousGeneration);
+ }
}
if (PP.getHeaderSearchInfo()
@@ -4320,6 +4346,9 @@ ASTReader::ASTReadResult ASTReader::ReadExtensionBlock(ModuleFile &F) {
}
void ASTReader::InitializeContext() {
+ assert(ContextObj && "no context to initialize");
+ ASTContext &Context = *ContextObj;
+
// If there's a listener, notify them that we "read" the translation unit.
if (DeserializationListener)
DeserializationListener->DeclRead(PREDEF_DECL_TRANSLATION_UNIT_ID,
@@ -5054,8 +5083,8 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
break;
}
case SUBMODULE_REQUIRES: {
- CurrentModule->addRequirement(Blob, Record[0], Context.getLangOpts(),
- Context.getTargetInfo());
+ CurrentModule->addRequirement(Blob, Record[0], PP.getLangOpts(),
+ PP.getTargetInfo());
break;
}
@@ -5081,10 +5110,12 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
}
case SUBMODULE_INITIALIZERS:
+ if (!ContextObj)
+ break;
SmallVector<uint32_t, 16> Inits;
for (auto &ID : Record)
Inits.push_back(getGlobalDeclID(F, ID));
- Context.addLazyModuleInitializers(CurrentModule, Inits);
+ ContextObj->addLazyModuleInitializers(CurrentModule, Inits);
break;
}
}
@@ -5705,6 +5736,8 @@ ASTReader::RecordLocation ASTReader::TypeCursorForIndex(unsigned Index) {
/// location. It is a helper routine for GetType, which deals with reading type
/// IDs.
QualType ASTReader::readTypeRecord(unsigned Index) {
+ assert(ContextObj && "reading type with no AST context");
+ ASTContext &Context = *ContextObj;
RecordLocation Loc = TypeCursorForIndex(Index);
BitstreamCursor &DeclsCursor = Loc.F->DeclsCursor;
@@ -6561,6 +6594,9 @@ ASTReader::GetTypeSourceInfo(ModuleFile &F, const ASTReader::RecordData &Record,
}
QualType ASTReader::GetType(TypeID ID) {
+ assert(ContextObj && "reading type with no AST context");
+ ASTContext &Context = *ContextObj;
+
unsigned FastQuals = ID & Qualifiers::FastMask;
unsigned Index = ID >> Qualifiers::FastWidth;
@@ -6892,6 +6928,9 @@ ASTReader::GetExternalCXXCtorInitializers(uint64_t Offset) {
}
CXXBaseSpecifier *ASTReader::GetExternalCXXBaseSpecifiers(uint64_t Offset) {
+ assert(ContextObj && "reading base specifiers with no AST context");
+ ASTContext &Context = *ContextObj;
+
RecordLocation Loc = getLocalBitOffset(Offset);
BitstreamCursor &Cursor = Loc.F->DeclsCursor;
SavedStreamPosition SavedPosition(Cursor);
@@ -7023,8 +7062,9 @@ static Decl *getPredefinedDecl(ASTContext &Context, PredefinedDeclIDs ID) {
}
Decl *ASTReader::GetExistingDecl(DeclID ID) {
+ assert(ContextObj && "reading decl with no AST context");
if (ID < NUM_PREDEF_DECL_IDS) {
- Decl *D = getPredefinedDecl(Context, (PredefinedDeclIDs)ID);
+ Decl *D = getPredefinedDecl(*ContextObj, (PredefinedDeclIDs)ID);
if (D) {
// Track that we have merged the declaration with ID \p ID into the
// pre-existing predefined declaration \p D.
@@ -7569,7 +7609,7 @@ IdentifierInfo *ASTReader::get(StringRef Name) {
// all interesting declarations, and don't need to use the scope for name
// lookups). Perform the lookup in PCH files, though, since we don't build
// a complete initial identifier table if we're carrying on from a PCH.
- if (Context.getLangOpts().CPlusPlus) {
+ if (PP.getLangOpts().CPlusPlus) {
for (auto F : ModuleMgr.pch_modules())
if (Visitor(*F))
break;
@@ -8223,7 +8263,7 @@ ASTReader::getSourceDescriptor(unsigned ID) {
return ExternalASTSource::ASTSourceDescriptor(*M);
// If there is only a single PCH, return it instead.
- // Chained PCH are not suported.
+ // Chained PCH are not supported.
const auto &PCHChain = ModuleMgr.pch_modules();
if (std::distance(std::begin(PCHChain), std::end(PCHChain))) {
ModuleFile &MF = ModuleMgr.getPrimaryModule();
@@ -8299,6 +8339,7 @@ ASTReader::getGlobalSelectorID(ModuleFile &M, unsigned LocalID) const {
DeclarationName
ASTReader::ReadDeclarationName(ModuleFile &F,
const RecordData &Record, unsigned &Idx) {
+ ASTContext &Context = getContext();
DeclarationName::NameKind Kind = (DeclarationName::NameKind)Record[Idx++];
switch (Kind) {
case DeclarationName::Identifier:
@@ -8389,7 +8430,8 @@ void ASTReader::ReadQualifierInfo(ModuleFile &F, QualifierInfo &Info,
unsigned NumTPLists = Record[Idx++];
Info.NumTemplParamLists = NumTPLists;
if (NumTPLists) {
- Info.TemplParamLists = new (Context) TemplateParameterList*[NumTPLists];
+ Info.TemplParamLists =
+ new (getContext()) TemplateParameterList *[NumTPLists];
for (unsigned i = 0; i != NumTPLists; ++i)
Info.TemplParamLists[i] = ReadTemplateParameterList(F, Record, Idx);
}
@@ -8398,6 +8440,7 @@ void ASTReader::ReadQualifierInfo(ModuleFile &F, QualifierInfo &Info,
TemplateName
ASTReader::ReadTemplateName(ModuleFile &F, const RecordData &Record,
unsigned &Idx) {
+ ASTContext &Context = getContext();
TemplateName::NameKind Kind = (TemplateName::NameKind)Record[Idx++];
switch (Kind) {
case TemplateName::Template:
@@ -8458,6 +8501,7 @@ TemplateArgument ASTReader::ReadTemplateArgument(ModuleFile &F,
const RecordData &Record,
unsigned &Idx,
bool Canonicalize) {
+ ASTContext &Context = getContext();
if (Canonicalize) {
// The caller wants a canonical template argument. Sometimes the AST only
// wants template arguments in canonical form (particularly as the template
@@ -8521,9 +8565,8 @@ ASTReader::ReadTemplateParameterList(ModuleFile &F,
Params.push_back(ReadDeclAs<NamedDecl>(F, Record, Idx));
// TODO: Concepts
- TemplateParameterList* TemplateParams =
- TemplateParameterList::Create(Context, TemplateLoc, LAngleLoc,
- Params, RAngleLoc, nullptr);
+ TemplateParameterList *TemplateParams = TemplateParameterList::Create(
+ getContext(), TemplateLoc, LAngleLoc, Params, RAngleLoc, nullptr);
return TemplateParams;
}
@@ -8542,11 +8585,11 @@ ReadTemplateArgumentList(SmallVectorImpl<TemplateArgument> &TemplArgs,
void ASTReader::ReadUnresolvedSet(ModuleFile &F, LazyASTUnresolvedSet &Set,
const RecordData &Record, unsigned &Idx) {
unsigned NumDecls = Record[Idx++];
- Set.reserve(Context, NumDecls);
+ Set.reserve(getContext(), NumDecls);
while (NumDecls--) {
DeclID ID = ReadDeclID(F, Record, Idx);
AccessSpecifier AS = (AccessSpecifier)Record[Idx++];
- Set.addLazyDecl(Context, ID, AS);
+ Set.addLazyDecl(getContext(), ID, AS);
}
}
@@ -8569,6 +8612,7 @@ ASTReader::ReadCXXBaseSpecifier(ModuleFile &F,
CXXCtorInitializer **
ASTReader::ReadCXXCtorInitializers(ModuleFile &F, const RecordData &Record,
unsigned &Idx) {
+ ASTContext &Context = getContext();
unsigned NumInitializers = Record[Idx++];
assert(NumInitializers && "wrote ctor initializers but have no inits");
auto **CtorInitializers = new (Context) CXXCtorInitializer*[NumInitializers];
@@ -8634,6 +8678,7 @@ ASTReader::ReadCXXCtorInitializers(ModuleFile &F, const RecordData &Record,
NestedNameSpecifier *
ASTReader::ReadNestedNameSpecifier(ModuleFile &F,
const RecordData &Record, unsigned &Idx) {
+ ASTContext &Context = getContext();
unsigned N = Record[Idx++];
NestedNameSpecifier *NNS = nullptr, *Prev = nullptr;
for (unsigned I = 0; I != N; ++I) {
@@ -8689,6 +8734,7 @@ ASTReader::ReadNestedNameSpecifier(ModuleFile &F,
NestedNameSpecifierLoc
ASTReader::ReadNestedNameSpecifierLoc(ModuleFile &F, const RecordData &Record,
unsigned &Idx) {
+ ASTContext &Context = getContext();
unsigned N = Record[Idx++];
NestedNameSpecifierLocBuilder Builder;
for (unsigned I = 0; I != N; ++I) {
@@ -8810,7 +8856,7 @@ CXXTemporary *ASTReader::ReadCXXTemporary(ModuleFile &F,
const RecordData &Record,
unsigned &Idx) {
CXXDestructorDecl *Decl = ReadDeclAs<CXXDestructorDecl>(F, Record, Idx);
- return CXXTemporary::Create(Context, Decl);
+ return CXXTemporary::Create(getContext(), Decl);
}
DiagnosticBuilder ASTReader::Diag(unsigned DiagID) const {
@@ -8846,6 +8892,7 @@ void ASTReader::ClearSwitchCaseIDs() {
}
void ASTReader::ReadComments() {
+ ASTContext &Context = getContext();
std::vector<RawComment *> Comments;
for (SmallVectorImpl<std::pair<BitstreamCursor,
serialization::ModuleFile *> >::iterator
@@ -8915,6 +8962,19 @@ void ASTReader::visitInputFiles(serialization::ModuleFile &MF,
}
}
+void ASTReader::visitTopLevelModuleMaps(
+ serialization::ModuleFile &MF,
+ llvm::function_ref<void(const FileEntry *FE)> Visitor) {
+ unsigned NumInputs = MF.InputFilesLoaded.size();
+ for (unsigned I = 0; I < NumInputs; ++I) {
+ InputFileInfo IFI = readInputFileInfo(MF, I + 1);
+ if (IFI.TopLevelModuleMap)
+ // FIXME: This unnecessarily re-reads the InputFileInfo.
+ if (auto *FE = getInputFile(MF, I + 1).getFile())
+ Visitor(FE);
+ }
+}
+
std::string ASTReader::getOwningModuleNameForDiagnostic(const Decl *D) {
// If we know the owning module, use it.
if (Module *M = D->getImportedOwningModule())
@@ -9514,8 +9574,8 @@ void ASTReader::diagnoseOdrViolations() {
break;
}
- assert(
- Context.hasSameType(FirstField->getType(), SecondField->getType()));
+ assert(getContext().hasSameType(FirstField->getType(),
+ SecondField->getType()));
QualType FirstType = FirstField->getType();
QualType SecondType = SecondField->getType();
@@ -9966,10 +10026,10 @@ void ASTReader::FinishedDeserializing() {
ProcessingUpdatesRAIIObj ProcessingUpdates(*this);
auto *FPT = Update.second->getType()->castAs<FunctionProtoType>();
auto ESI = FPT->getExtProtoInfo().ExceptionSpec;
- if (auto *Listener = Context.getASTMutationListener())
+ if (auto *Listener = getContext().getASTMutationListener())
Listener->ResolvedExceptionSpec(cast<FunctionDecl>(Update.second));
for (auto *Redecl : Update.second->redecls())
- Context.adjustExceptionSpec(cast<FunctionDecl>(Redecl), ESI);
+ getContext().adjustExceptionSpec(cast<FunctionDecl>(Redecl), ESI);
}
}
@@ -10011,7 +10071,7 @@ void ASTReader::pushExternalDeclIntoScope(NamedDecl *D, DeclarationName Name) {
}
}
-ASTReader::ASTReader(Preprocessor &PP, ASTContext &Context,
+ASTReader::ASTReader(Preprocessor &PP, ASTContext *Context,
const PCHContainerReader &PCHContainerRdr,
ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
StringRef isysroot, bool DisableValidation,
@@ -10024,7 +10084,7 @@ ASTReader::ASTReader(Preprocessor &PP, ASTContext &Context,
: cast<ASTReaderListener>(new PCHValidator(PP, *this))),
SourceMgr(PP.getSourceManager()), FileMgr(PP.getFileManager()),
PCHContainerRdr(PCHContainerRdr), Diags(PP.getDiagnostics()), PP(PP),
- Context(Context),
+ ContextObj(Context),
ModuleMgr(PP.getFileManager(), PP.getPCMCache(), PCHContainerRdr),
PCMCache(PP.getPCMCache()), DummyIdResolver(PP),
ReadTimer(std::move(ReadTimer)), isysroot(isysroot),
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index 07ab421cfc51..4d9ddd2ff506 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -126,6 +126,9 @@ namespace clang {
void ReadObjCDefinitionData(struct ObjCInterfaceDecl::DefinitionData &Data);
void MergeDefinitionData(ObjCInterfaceDecl *D,
struct ObjCInterfaceDecl::DefinitionData &&NewDD);
+ void ReadObjCDefinitionData(struct ObjCProtocolDecl::DefinitionData &Data);
+ void MergeDefinitionData(ObjCProtocolDecl *D,
+ struct ObjCProtocolDecl::DefinitionData &&NewDD);
static NamedDecl *getAnonymousDeclForMerging(ASTReader &Reader,
DeclContext *DC,
@@ -216,6 +219,30 @@ namespace clang {
TypedefNameForLinkage(nullptr), HasPendingBody(false),
IsDeclMarkedUsed(false) {}
+ template <typename T> static
+ void AddLazySpecializations(T *D,
+ SmallVectorImpl<serialization::DeclID>& IDs) {
+ if (IDs.empty())
+ return;
+
+ // FIXME: We should avoid this pattern of getting the ASTContext.
+ ASTContext &C = D->getASTContext();
+
+ auto *&LazySpecializations = D->getCommonPtr()->LazySpecializations;
+
+ if (auto &Old = LazySpecializations) {
+ IDs.insert(IDs.end(), Old + 1, Old + 1 + Old[0]);
+ std::sort(IDs.begin(), IDs.end());
+ IDs.erase(std::unique(IDs.begin(), IDs.end()), IDs.end());
+ }
+
+ auto *Result = new (C) serialization::DeclID[1 + IDs.size()];
+ *Result = IDs.size();
+ std::copy(IDs.begin(), IDs.end(), Result + 1);
+
+ LazySpecializations = Result;
+ }
+
template <typename DeclT>
static Decl *getMostRecentDeclImpl(Redeclarable<DeclT> *D);
static Decl *getMostRecentDeclImpl(...);
@@ -244,7 +271,7 @@ namespace clang {
void ReadFunctionDefinition(FunctionDecl *FD);
void Visit(Decl *D);
- void UpdateDecl(Decl *D);
+ void UpdateDecl(Decl *D, llvm::SmallVectorImpl<serialization::DeclID>&);
static void setNextObjCCategory(ObjCCategoryDecl *Cat,
ObjCCategoryDecl *Next) {
@@ -1045,18 +1072,8 @@ void ASTDeclReader::VisitObjCIvarDecl(ObjCIvarDecl *IVD) {
IVD->setSynthesize(synth);
}
-void ASTDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) {
- RedeclarableResult Redecl = VisitRedeclarable(PD);
- VisitObjCContainerDecl(PD);
- mergeRedeclarable(PD, Redecl);
-
- if (Record.readInt()) {
- // Read the definition.
- PD->allocateDefinitionData();
-
- // Set the definition data of the canonical declaration, so other
- // redeclarations will see it.
- PD->getCanonicalDecl()->Data = PD->Data;
+void ASTDeclReader::ReadObjCDefinitionData(
+ struct ObjCProtocolDecl::DefinitionData &Data) {
unsigned NumProtoRefs = Record.readInt();
SmallVector<ObjCProtocolDecl *, 16> ProtoRefs;
@@ -1067,9 +1084,37 @@ void ASTDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) {
ProtoLocs.reserve(NumProtoRefs);
for (unsigned I = 0; I != NumProtoRefs; ++I)
ProtoLocs.push_back(ReadSourceLocation());
- PD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(),
- Reader.getContext());
+ Data.ReferencedProtocols.set(ProtoRefs.data(), NumProtoRefs,
+ ProtoLocs.data(), Reader.getContext());
+}
+
+void ASTDeclReader::MergeDefinitionData(ObjCProtocolDecl *D,
+ struct ObjCProtocolDecl::DefinitionData &&NewDD) {
+ // FIXME: odr checking?
+}
+
+void ASTDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) {
+ RedeclarableResult Redecl = VisitRedeclarable(PD);
+ VisitObjCContainerDecl(PD);
+ mergeRedeclarable(PD, Redecl);
+
+ if (Record.readInt()) {
+ // Read the definition.
+ PD->allocateDefinitionData();
+
+ ReadObjCDefinitionData(PD->data());
+ ObjCProtocolDecl *Canon = PD->getCanonicalDecl();
+ if (Canon->Data.getPointer()) {
+ // If we already have a definition, keep the definition invariant and
+ // merge the data.
+ MergeDefinitionData(Canon, std::move(PD->data()));
+ PD->Data = Canon->Data;
+ } else {
+ // Set the definition data of the canonical declaration, so other
+ // redeclarations will see it.
+ PD->getCanonicalDecl()->Data = PD->Data;
+ }
// Note that we have deserialized a definition.
Reader.PendingDefinitions.insert(PD);
} else {
@@ -1566,8 +1611,8 @@ void ASTDeclReader::ReadCXXDefinitionData(
Lambda.NumExplicitCaptures = Record.readInt();
Lambda.ManglingNumber = Record.readInt();
Lambda.ContextDecl = ReadDeclID();
- Lambda.Captures
- = (Capture*)Reader.Context.Allocate(sizeof(Capture)*Lambda.NumCaptures);
+ Lambda.Captures = (Capture *)Reader.getContext().Allocate(
+ sizeof(Capture) * Lambda.NumCaptures);
Capture *ToCapture = Lambda.Captures;
Lambda.MethodTyInfo = GetTypeSourceInfo();
for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) {
@@ -1950,21 +1995,6 @@ ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
return Redecl;
}
-static DeclID *newDeclIDList(ASTContext &Context, DeclID *Old,
- SmallVectorImpl<DeclID> &IDs) {
- assert(!IDs.empty() && "no IDs to add to list");
- if (Old) {
- IDs.insert(IDs.end(), Old + 1, Old + 1 + Old[0]);
- std::sort(IDs.begin(), IDs.end());
- IDs.erase(std::unique(IDs.begin(), IDs.end()), IDs.end());
- }
-
- auto *Result = new (Context) DeclID[1 + IDs.size()];
- *Result = IDs.size();
- std::copy(IDs.begin(), IDs.end(), Result + 1);
- return Result;
-}
-
void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) {
RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D);
@@ -1973,19 +2003,14 @@ void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) {
// the specializations.
SmallVector<serialization::DeclID, 32> SpecIDs;
ReadDeclIDList(SpecIDs);
-
- if (!SpecIDs.empty()) {
- auto *CommonPtr = D->getCommonPtr();
- CommonPtr->LazySpecializations = newDeclIDList(
- Reader.getContext(), CommonPtr->LazySpecializations, SpecIDs);
- }
+ ASTDeclReader::AddLazySpecializations(D, SpecIDs);
}
if (D->getTemplatedDecl()->TemplateOrInstantiation) {
// We were loaded before our templated declaration was. We've not set up
// its corresponding type yet (see VisitCXXRecordDeclImpl), so reconstruct
// it now.
- Reader.Context.getInjectedClassNameType(
+ Reader.getContext().getInjectedClassNameType(
D->getTemplatedDecl(), D->getInjectedClassNameSpecialization());
}
}
@@ -2005,12 +2030,7 @@ void ASTDeclReader::VisitVarTemplateDecl(VarTemplateDecl *D) {
// the specializations.
SmallVector<serialization::DeclID, 32> SpecIDs;
ReadDeclIDList(SpecIDs);
-
- if (!SpecIDs.empty()) {
- auto *CommonPtr = D->getCommonPtr();
- CommonPtr->LazySpecializations = newDeclIDList(
- Reader.getContext(), CommonPtr->LazySpecializations, SpecIDs);
- }
+ ASTDeclReader::AddLazySpecializations(D, SpecIDs);
}
}
@@ -2116,12 +2136,7 @@ void ASTDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
// This FunctionTemplateDecl owns a CommonPtr; read it.
SmallVector<serialization::DeclID, 32> SpecIDs;
ReadDeclIDList(SpecIDs);
-
- if (!SpecIDs.empty()) {
- auto *CommonPtr = D->getCommonPtr();
- CommonPtr->LazySpecializations = newDeclIDList(
- Reader.getContext(), CommonPtr->LazySpecializations, SpecIDs);
- }
+ ASTDeclReader::AddLazySpecializations(D, SpecIDs);
}
}
@@ -2472,8 +2487,8 @@ void ASTDeclReader::mergeMergeable(Mergeable<T> *D) {
if (FindExistingResult ExistingRes = findExisting(static_cast<T*>(D)))
if (T *Existing = ExistingRes)
- Reader.Context.setPrimaryMergedDecl(static_cast<T*>(D),
- Existing->getCanonicalDecl());
+ Reader.getContext().setPrimaryMergedDecl(static_cast<T *>(D),
+ Existing->getCanonicalDecl());
}
void ASTDeclReader::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) {
@@ -2509,6 +2524,7 @@ void ASTReader::ReadAttributes(ASTRecordReader &Record, AttrVec &Attrs) {
Attr *New = nullptr;
attr::Kind Kind = (attr::Kind)Record.readInt();
SourceRange Range = Record.readSourceRange();
+ ASTContext &Context = getContext();
#include "clang/Serialization/AttrPCHRead.inc"
@@ -2907,7 +2923,7 @@ DeclContext *ASTDeclReader::getPrimaryContextForMerging(ASTReader &Reader,
// commit to DC being the canonical definition now, and will fix this when
// we load the update record.
if (!DD) {
- DD = new (Reader.Context) struct CXXRecordDecl::DefinitionData(RD);
+ DD = new (Reader.getContext()) struct CXXRecordDecl::DefinitionData(RD);
RD->IsCompleteDefinition = true;
RD->DefinitionData = DD;
RD->getCanonicalDecl()->DefinitionData = DD;
@@ -3352,6 +3368,7 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
ASTDeclReader Reader(*this, Record, Loc, ID, DeclLoc);
unsigned Code = DeclsCursor.ReadCode();
+ ASTContext &Context = getContext();
Decl *D = nullptr;
switch ((DeclCode)Record.readRecord(DeclsCursor, Code)) {
case DECL_CONTEXT_LEXICAL:
@@ -3652,7 +3669,7 @@ void ASTReader::PassInterestingDeclsToConsumer() {
while (!PotentiallyInterestingDecls.empty()) {
InterestingDecl D = PotentiallyInterestingDecls.front();
PotentiallyInterestingDecls.pop_front();
- if (isConsumerInterestedIn(Context, D.getDecl(), D.hasPendingBody()))
+ if (isConsumerInterestedIn(getContext(), D.getDecl(), D.hasPendingBody()))
PassInterestingDeclToConsumer(D.getDecl());
}
}
@@ -3665,6 +3682,9 @@ void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) {
Decl *D = Record.D;
ProcessingUpdatesRAIIObj ProcessingUpdates(*this);
DeclUpdateOffsetsMap::iterator UpdI = DeclUpdateOffsets.find(ID);
+
+ llvm::SmallVector<serialization::DeclID, 8> PendingLazySpecializationIDs;
+
if (UpdI != DeclUpdateOffsets.end()) {
auto UpdateOffsets = std::move(UpdI->second);
DeclUpdateOffsets.erase(UpdI);
@@ -3674,7 +3694,7 @@ void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) {
// to isConsumerInterestedIn because it is unsafe to call in the
// current ASTReader state.
bool WasInteresting =
- Record.JustLoaded || isConsumerInterestedIn(Context, D, false);
+ Record.JustLoaded || isConsumerInterestedIn(getContext(), D, false);
for (auto &FileAndOffset : UpdateOffsets) {
ModuleFile *F = FileAndOffset.first;
uint64_t Offset = FileAndOffset.second;
@@ -3689,18 +3709,29 @@ void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) {
ASTDeclReader Reader(*this, Record, RecordLocation(F, Offset), ID,
SourceLocation());
- Reader.UpdateDecl(D);
+ Reader.UpdateDecl(D, PendingLazySpecializationIDs);
// We might have made this declaration interesting. If so, remember that
// we need to hand it off to the consumer.
if (!WasInteresting &&
- isConsumerInterestedIn(Context, D, Reader.hasPendingBody())) {
+ isConsumerInterestedIn(getContext(), D, Reader.hasPendingBody())) {
PotentiallyInterestingDecls.push_back(
InterestingDecl(D, Reader.hasPendingBody()));
WasInteresting = true;
}
}
}
+ // Add the lazy specializations to the template.
+ assert((PendingLazySpecializationIDs.empty() || isa<ClassTemplateDecl>(D) ||
+ isa<FunctionTemplateDecl>(D) || isa<VarTemplateDecl>(D)) &&
+ "Must not have pending specializations");
+ if (auto *CTD = dyn_cast<ClassTemplateDecl>(D))
+ ASTDeclReader::AddLazySpecializations(CTD, PendingLazySpecializationIDs);
+ else if (auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
+ ASTDeclReader::AddLazySpecializations(FTD, PendingLazySpecializationIDs);
+ else if (auto *VTD = dyn_cast<VarTemplateDecl>(D))
+ ASTDeclReader::AddLazySpecializations(VTD, PendingLazySpecializationIDs);
+ PendingLazySpecializationIDs.clear();
// Load the pending visible updates for this decl context, if it has any.
auto I = PendingVisibleUpdates.find(ID);
@@ -3897,7 +3928,8 @@ static void forAllLaterRedecls(DeclT *D, Fn F) {
}
}
-void ASTDeclReader::UpdateDecl(Decl *D) {
+void ASTDeclReader::UpdateDecl(Decl *D,
+ llvm::SmallVectorImpl<serialization::DeclID> &PendingLazySpecializationIDs) {
while (Record.getIdx() < Record.size()) {
switch ((DeclUpdateKind)Record.readInt()) {
case UPD_CXX_ADDED_IMPLICIT_MEMBER: {
@@ -3913,8 +3945,8 @@ void ASTDeclReader::UpdateDecl(Decl *D) {
}
case UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION:
- // It will be added to the template's specializations set when loaded.
- (void)Record.readDecl();
+ // It will be added to the template's lazy specialization set.
+ PendingLazySpecializationIDs.push_back(ReadDeclID());
break;
case UPD_CXX_ADDED_ANONYMOUS_NAMESPACE: {
@@ -4083,7 +4115,7 @@ void ASTDeclReader::UpdateDecl(Decl *D) {
// FIXME: If the exception specification is already present, check that it
// matches.
if (isUnresolvedExceptionSpec(FPT->getExceptionSpecType())) {
- FD->setType(Reader.Context.getFunctionType(
+ FD->setType(Reader.getContext().getFunctionType(
FPT->getReturnType(), FPT->getParamTypes(),
FPT->getExtProtoInfo().withExceptionSpec(ESI)));
@@ -4101,28 +4133,31 @@ void ASTDeclReader::UpdateDecl(Decl *D) {
for (auto *Redecl : merged_redecls(D)) {
// FIXME: If the return type is already deduced, check that it matches.
FunctionDecl *FD = cast<FunctionDecl>(Redecl);
- Reader.Context.adjustDeducedFunctionResultType(FD, DeducedResultType);
+ Reader.getContext().adjustDeducedFunctionResultType(FD,
+ DeducedResultType);
}
break;
}
case UPD_DECL_MARKED_USED: {
// Maintain AST consistency: any later redeclarations are used too.
- D->markUsed(Reader.Context);
+ D->markUsed(Reader.getContext());
break;
}
case UPD_MANGLING_NUMBER:
- Reader.Context.setManglingNumber(cast<NamedDecl>(D), Record.readInt());
+ Reader.getContext().setManglingNumber(cast<NamedDecl>(D),
+ Record.readInt());
break;
case UPD_STATIC_LOCAL_NUMBER:
- Reader.Context.setStaticLocalNumber(cast<VarDecl>(D), Record.readInt());
+ Reader.getContext().setStaticLocalNumber(cast<VarDecl>(D),
+ Record.readInt());
break;
case UPD_DECL_MARKED_OPENMP_THREADPRIVATE:
- D->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
- Reader.Context, ReadSourceRange()));
+ D->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(Reader.getContext(),
+ ReadSourceRange()));
break;
case UPD_DECL_EXPORTED: {
diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp
index 3d314a85ff17..afee50ffa3b9 100644
--- a/lib/Serialization/ASTReaderStmt.cpp
+++ b/lib/Serialization/ASTReaderStmt.cpp
@@ -2954,6 +2954,7 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
break;
}
+ ASTContext &Context = getContext();
Stmt *S = nullptr;
bool Finished = false;
bool IsStmtReference = false;
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index 1c0db14ced14..c6129d326cb6 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -1692,6 +1692,7 @@ namespace {
bool IsSystemFile;
bool IsTransient;
bool BufferOverridden;
+ bool IsTopLevelModuleMap;
};
} // end anonymous namespace
@@ -1710,6 +1711,7 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr,
IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 32)); // Modification time
IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Overridden
IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Transient
+ IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Module map
IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name
unsigned IFAbbrevCode = Stream.EmitAbbrev(std::move(IFAbbrev));
@@ -1724,7 +1726,8 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr,
// We only care about file entries that were not overridden.
if (!SLoc->isFile())
continue;
- const SrcMgr::ContentCache *Cache = SLoc->getFile().getContentCache();
+ const SrcMgr::FileInfo &File = SLoc->getFile();
+ const SrcMgr::ContentCache *Cache = File.getContentCache();
if (!Cache->OrigEntry)
continue;
@@ -1733,6 +1736,8 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr,
Entry.IsSystemFile = Cache->IsSystemFile;
Entry.IsTransient = Cache->IsTransient;
Entry.BufferOverridden = Cache->BufferOverridden;
+ Entry.IsTopLevelModuleMap = isModuleMap(File.getFileCharacteristic()) &&
+ File.getIncludeLoc().isInvalid();
if (Cache->IsSystemFile)
SortedFiles.push_back(Entry);
else
@@ -1763,7 +1768,8 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr,
(uint64_t)Entry.File->getSize(),
(uint64_t)getTimestampForOutput(Entry.File),
Entry.BufferOverridden,
- Entry.IsTransient};
+ Entry.IsTransient,
+ Entry.IsTopLevelModuleMap};
EmitRecordWithPath(IFAbbrevCode, Record, Entry.File->getName());
}
@@ -1798,7 +1804,7 @@ static unsigned CreateSLocFileAbbrev(llvm::BitstreamWriter &Stream) {
Abbrev->Add(BitCodeAbbrevOp(SM_SLOC_FILE_ENTRY));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Include location
- Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Characteristic
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Characteristic
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Line directives
// FileEntry fields.
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Input File ID
@@ -1817,7 +1823,7 @@ static unsigned CreateSLocBufferAbbrev(llvm::BitstreamWriter &Stream) {
Abbrev->Add(BitCodeAbbrevOp(SM_SLOC_BUFFER_ENTRY));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Include location
- Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Characteristic
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Characteristic
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Line directives
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Buffer name blob
return Stream.EmitAbbrev(std::move(Abbrev));
@@ -1925,8 +1931,8 @@ namespace {
endian::Writer<little> LE(Out);
uint64_t Start = Out.tell(); (void)Start;
- unsigned char Flags = (Data.HFI.isImport << 4)
- | (Data.HFI.isPragmaOnce << 3)
+ unsigned char Flags = (Data.HFI.isImport << 5)
+ | (Data.HFI.isPragmaOnce << 4)
| (Data.HFI.DirInfo << 1)
| Data.HFI.IndexHeaderMapHeader;
LE.write<uint8_t>(Flags);
diff --git a/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp b/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
index 26bf597bd950..7f9a00ff876d 100644
--- a/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
@@ -45,6 +45,8 @@ class UnixAPIChecker : public Checker< check::PreStmt<CallExpr> > {
mutable Optional<uint64_t> Val_O_CREAT;
public:
+ DefaultBool CheckMisuse, CheckPortability;
+
void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
void CheckOpen(CheckerContext &C, const CallExpr *CE) const;
@@ -437,29 +439,42 @@ void UnixAPIChecker::checkPreStmt(const CallExpr *CE,
if (FName.empty())
return;
- SubChecker SC =
- llvm::StringSwitch<SubChecker>(FName)
- .Case("open", &UnixAPIChecker::CheckOpen)
- .Case("openat", &UnixAPIChecker::CheckOpenAt)
- .Case("pthread_once", &UnixAPIChecker::CheckPthreadOnce)
- .Case("calloc", &UnixAPIChecker::CheckCallocZero)
- .Case("malloc", &UnixAPIChecker::CheckMallocZero)
- .Case("realloc", &UnixAPIChecker::CheckReallocZero)
- .Case("reallocf", &UnixAPIChecker::CheckReallocfZero)
- .Cases("alloca", "__builtin_alloca", &UnixAPIChecker::CheckAllocaZero)
- .Case("__builtin_alloca_with_align",
- &UnixAPIChecker::CheckAllocaWithAlignZero)
- .Case("valloc", &UnixAPIChecker::CheckVallocZero)
- .Default(nullptr);
-
- if (SC)
- (this->*SC)(C, CE);
+ if (CheckMisuse) {
+ if (SubChecker SC =
+ llvm::StringSwitch<SubChecker>(FName)
+ .Case("open", &UnixAPIChecker::CheckOpen)
+ .Case("openat", &UnixAPIChecker::CheckOpenAt)
+ .Case("pthread_once", &UnixAPIChecker::CheckPthreadOnce)
+ .Default(nullptr)) {
+ (this->*SC)(C, CE);
+ }
+ }
+ if (CheckPortability) {
+ if (SubChecker SC =
+ llvm::StringSwitch<SubChecker>(FName)
+ .Case("calloc", &UnixAPIChecker::CheckCallocZero)
+ .Case("malloc", &UnixAPIChecker::CheckMallocZero)
+ .Case("realloc", &UnixAPIChecker::CheckReallocZero)
+ .Case("reallocf", &UnixAPIChecker::CheckReallocfZero)
+ .Cases("alloca", "__builtin_alloca",
+ &UnixAPIChecker::CheckAllocaZero)
+ .Case("__builtin_alloca_with_align",
+ &UnixAPIChecker::CheckAllocaWithAlignZero)
+ .Case("valloc", &UnixAPIChecker::CheckVallocZero)
+ .Default(nullptr)) {
+ (this->*SC)(C, CE);
+ }
+ }
}
//===----------------------------------------------------------------------===//
// Registration.
//===----------------------------------------------------------------------===//
-void ento::registerUnixAPIChecker(CheckerManager &mgr) {
- mgr.registerChecker<UnixAPIChecker>();
-}
+#define REGISTER_CHECKER(Name) \
+ void ento::registerUnixAPI##Name##Checker(CheckerManager &mgr) { \
+ mgr.registerChecker<UnixAPIChecker>()->Check##Name = true; \
+ }
+
+REGISTER_CHECKER(Misuse)
+REGISTER_CHECKER(Portability)
diff --git a/lib/Tooling/CompilationDatabase.cpp b/lib/Tooling/CompilationDatabase.cpp
index 77c5b547ca09..0e835579e04e 100644
--- a/lib/Tooling/CompilationDatabase.cpp
+++ b/lib/Tooling/CompilationDatabase.cpp
@@ -255,10 +255,12 @@ static bool stripPositionalArgs(std::vector<const char *> Args,
CompileJobAnalyzer CompileAnalyzer;
for (const auto &Cmd : Jobs) {
- // Collect only for Assemble jobs. If we do all jobs we get duplicates
- // since Link jobs point to Assemble jobs as inputs.
- if (Cmd.getSource().getKind() == driver::Action::AssembleJobClass)
+ // Collect only for Assemble and Compile jobs. If we do all jobs we get
+ // duplicates since Link jobs point to Assemble jobs as inputs.
+ if (Cmd.getSource().getKind() == driver::Action::AssembleJobClass ||
+ Cmd.getSource().getKind() == driver::Action::CompileJobClass) {
CompileAnalyzer.run(&Cmd.getSource());
+ }
}
if (CompileAnalyzer.Inputs.empty()) {
diff --git a/lib/Tooling/Refactoring/AtomicChange.cpp b/lib/Tooling/Refactoring/AtomicChange.cpp
index 321bbfa2866a..79dd346acf72 100644
--- a/lib/Tooling/Refactoring/AtomicChange.cpp
+++ b/lib/Tooling/Refactoring/AtomicChange.cpp
@@ -12,7 +12,6 @@
#include "llvm/Support/YAMLTraits.h"
#include <string>
-LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(std::string)
LLVM_YAML_IS_SEQUENCE_VECTOR(clang::tooling::AtomicChange)
namespace {
diff --git a/lib/Tooling/Refactoring/CMakeLists.txt b/lib/Tooling/Refactoring/CMakeLists.txt
index b2f9b4f4c0cd..288582fc1b6b 100644
--- a/lib/Tooling/Refactoring/CMakeLists.txt
+++ b/lib/Tooling/Refactoring/CMakeLists.txt
@@ -5,8 +5,16 @@ set(LLVM_LINK_COMPONENTS
add_clang_library(clangToolingRefactor
AtomicChange.cpp
+ Rename/RenamingAction.cpp
+ Rename/USRFinder.cpp
+ Rename/USRFindingAction.cpp
+ Rename/USRLocFinder.cpp
LINK_LIBS
+ clangAST
+ clangASTMatchers
clangBasic
+ clangIndex
+ clangLex
clangToolingCore
)
diff --git a/lib/Tooling/Refactoring/Rename/RenamingAction.cpp b/lib/Tooling/Refactoring/Rename/RenamingAction.cpp
new file mode 100644
index 000000000000..de6aba944a4a
--- /dev/null
+++ b/lib/Tooling/Refactoring/Rename/RenamingAction.cpp
@@ -0,0 +1,134 @@
+//===--- RenamingAction.cpp - Clang refactoring library -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Provides an action to rename every symbol at a point.
+///
+//===----------------------------------------------------------------------===//
+
+#include "clang/Tooling/Refactoring/Rename/RenamingAction.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendAction.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Tooling/CommonOptionsParser.h"
+#include "clang/Tooling/Refactoring.h"
+#include "clang/Tooling/Refactoring/Rename/USRLocFinder.h"
+#include "clang/Tooling/Tooling.h"
+#include <string>
+#include <vector>
+
+using namespace llvm;
+
+namespace clang {
+namespace tooling {
+
+class RenamingASTConsumer : public ASTConsumer {
+public:
+ RenamingASTConsumer(
+ const std::vector<std::string> &NewNames,
+ const std::vector<std::string> &PrevNames,
+ const std::vector<std::vector<std::string>> &USRList,
+ std::map<std::string, tooling::Replacements> &FileToReplaces,
+ bool PrintLocations)
+ : NewNames(NewNames), PrevNames(PrevNames), USRList(USRList),
+ FileToReplaces(FileToReplaces), PrintLocations(PrintLocations) {}
+
+ void HandleTranslationUnit(ASTContext &Context) override {
+ for (unsigned I = 0; I < NewNames.size(); ++I)
+ HandleOneRename(Context, NewNames[I], PrevNames[I], USRList[I]);
+ }
+
+ void HandleOneRename(ASTContext &Context, const std::string &NewName,
+ const std::string &PrevName,
+ const std::vector<std::string> &USRs) {
+ const SourceManager &SourceMgr = Context.getSourceManager();
+ std::vector<SourceLocation> RenamingCandidates;
+ std::vector<SourceLocation> NewCandidates;
+
+ NewCandidates = tooling::getLocationsOfUSRs(
+ USRs, PrevName, Context.getTranslationUnitDecl());
+ RenamingCandidates.insert(RenamingCandidates.end(), NewCandidates.begin(),
+ NewCandidates.end());
+
+ unsigned PrevNameLen = PrevName.length();
+ for (const auto &Loc : RenamingCandidates) {
+ if (PrintLocations) {
+ FullSourceLoc FullLoc(Loc, SourceMgr);
+ errs() << "clang-rename: renamed at: " << SourceMgr.getFilename(Loc)
+ << ":" << FullLoc.getSpellingLineNumber() << ":"
+ << FullLoc.getSpellingColumnNumber() << "\n";
+ }
+ // FIXME: better error handling.
+ tooling::Replacement Replace(SourceMgr, Loc, PrevNameLen, NewName);
+ llvm::Error Err = FileToReplaces[Replace.getFilePath()].add(Replace);
+ if (Err)
+ llvm::errs() << "Renaming failed in " << Replace.getFilePath() << "! "
+ << llvm::toString(std::move(Err)) << "\n";
+ }
+ }
+
+private:
+ const std::vector<std::string> &NewNames, &PrevNames;
+ const std::vector<std::vector<std::string>> &USRList;
+ std::map<std::string, tooling::Replacements> &FileToReplaces;
+ bool PrintLocations;
+};
+
+// A renamer to rename symbols which are identified by a give USRList to
+// new name.
+//
+// FIXME: Merge with the above RenamingASTConsumer.
+class USRSymbolRenamer : public ASTConsumer {
+public:
+ USRSymbolRenamer(const std::vector<std::string> &NewNames,
+ const std::vector<std::vector<std::string>> &USRList,
+ std::map<std::string, tooling::Replacements> &FileToReplaces)
+ : NewNames(NewNames), USRList(USRList), FileToReplaces(FileToReplaces) {
+ assert(USRList.size() == NewNames.size());
+ }
+
+ void HandleTranslationUnit(ASTContext &Context) override {
+ for (unsigned I = 0; I < NewNames.size(); ++I) {
+ // FIXME: Apply AtomicChanges directly once the refactoring APIs are
+ // ready.
+ auto AtomicChanges = tooling::createRenameAtomicChanges(
+ USRList[I], NewNames[I], Context.getTranslationUnitDecl());
+ for (const auto AtomicChange : AtomicChanges) {
+ for (const auto &Replace : AtomicChange.getReplacements()) {
+ llvm::Error Err = FileToReplaces[Replace.getFilePath()].add(Replace);
+ if (Err) {
+ llvm::errs() << "Renaming failed in " << Replace.getFilePath()
+ << "! " << llvm::toString(std::move(Err)) << "\n";
+ }
+ }
+ }
+ }
+ }
+
+private:
+ const std::vector<std::string> &NewNames;
+ const std::vector<std::vector<std::string>> &USRList;
+ std::map<std::string, tooling::Replacements> &FileToReplaces;
+};
+
+std::unique_ptr<ASTConsumer> RenamingAction::newASTConsumer() {
+ return llvm::make_unique<RenamingASTConsumer>(NewNames, PrevNames, USRList,
+ FileToReplaces, PrintLocations);
+}
+
+std::unique_ptr<ASTConsumer> QualifiedRenamingAction::newASTConsumer() {
+ return llvm::make_unique<USRSymbolRenamer>(NewNames, USRList, FileToReplaces);
+}
+
+} // end namespace tooling
+} // end namespace clang
diff --git a/lib/Tooling/Refactoring/Rename/USRFinder.cpp b/lib/Tooling/Refactoring/Rename/USRFinder.cpp
new file mode 100644
index 000000000000..f36387dafdbf
--- /dev/null
+++ b/lib/Tooling/Refactoring/Rename/USRFinder.cpp
@@ -0,0 +1,213 @@
+//===--- USRFinder.cpp - Clang refactoring library ------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file Implements a recursive AST visitor that finds the USR of a symbol at a
+/// point.
+///
+//===----------------------------------------------------------------------===//
+
+#include "clang/Tooling/Refactoring/Rename/USRFinder.h"
+#include "clang/AST/AST.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/Index/USRGeneration.h"
+#include "clang/Lex/Lexer.h"
+#include "llvm/ADT/SmallVector.h"
+
+using namespace llvm;
+
+namespace clang {
+namespace tooling {
+
+// NamedDeclFindingASTVisitor recursively visits each AST node to find the
+// symbol underneath the cursor.
+// FIXME: move to separate .h/.cc file if this gets too large.
+namespace {
+class NamedDeclFindingASTVisitor
+ : public clang::RecursiveASTVisitor<NamedDeclFindingASTVisitor> {
+public:
+ // \brief Finds the NamedDecl at a point in the source.
+ // \param Point the location in the source to search for the NamedDecl.
+ explicit NamedDeclFindingASTVisitor(const SourceLocation Point,
+ const ASTContext &Context)
+ : Result(nullptr), Point(Point), Context(Context) {}
+
+ // \brief Finds the NamedDecl for a name in the source.
+ // \param Name the fully qualified name.
+ explicit NamedDeclFindingASTVisitor(const std::string &Name,
+ const ASTContext &Context)
+ : Result(nullptr), Name(Name), Context(Context) {}
+
+ // Declaration visitors:
+
+ // \brief Checks if the point falls within the NameDecl. This covers every
+ // declaration of a named entity that we may come across. Usually, just
+ // checking if the point lies within the length of the name of the declaration
+ // and the start location is sufficient.
+ bool VisitNamedDecl(const NamedDecl *Decl) {
+ return dyn_cast<CXXConversionDecl>(Decl)
+ ? true
+ : setResult(Decl, Decl->getLocation(),
+ Decl->getNameAsString().length());
+ }
+
+ // Expression visitors:
+
+ bool VisitDeclRefExpr(const DeclRefExpr *Expr) {
+ const NamedDecl *Decl = Expr->getFoundDecl();
+ return setResult(Decl, Expr->getLocation(),
+ Decl->getNameAsString().length());
+ }
+
+ bool VisitMemberExpr(const MemberExpr *Expr) {
+ const NamedDecl *Decl = Expr->getFoundDecl().getDecl();
+ return setResult(Decl, Expr->getMemberLoc(),
+ Decl->getNameAsString().length());
+ }
+
+ // Other visitors:
+
+ bool VisitTypeLoc(const TypeLoc Loc) {
+ const SourceLocation TypeBeginLoc = Loc.getBeginLoc();
+ const SourceLocation TypeEndLoc = Lexer::getLocForEndOfToken(
+ TypeBeginLoc, 0, Context.getSourceManager(), Context.getLangOpts());
+ if (const auto *TemplateTypeParm =
+ dyn_cast<TemplateTypeParmType>(Loc.getType()))
+ return setResult(TemplateTypeParm->getDecl(), TypeBeginLoc, TypeEndLoc);
+ if (const auto *TemplateSpecType =
+ dyn_cast<TemplateSpecializationType>(Loc.getType())) {
+ return setResult(TemplateSpecType->getTemplateName().getAsTemplateDecl(),
+ TypeBeginLoc, TypeEndLoc);
+ }
+ return setResult(Loc.getType()->getAsCXXRecordDecl(), TypeBeginLoc,
+ TypeEndLoc);
+ }
+
+ bool VisitCXXConstructorDecl(clang::CXXConstructorDecl *ConstructorDecl) {
+ for (const auto *Initializer : ConstructorDecl->inits()) {
+ // Ignore implicit initializers.
+ if (!Initializer->isWritten())
+ continue;
+ if (const clang::FieldDecl *FieldDecl = Initializer->getMember()) {
+ const SourceLocation InitBeginLoc = Initializer->getSourceLocation(),
+ InitEndLoc = Lexer::getLocForEndOfToken(
+ InitBeginLoc, 0, Context.getSourceManager(),
+ Context.getLangOpts());
+ if (!setResult(FieldDecl, InitBeginLoc, InitEndLoc))
+ return false;
+ }
+ }
+ return true;
+ }
+
+ // Other:
+
+ const NamedDecl *getNamedDecl() { return Result; }
+
+ // \brief Determines if a namespace qualifier contains the point.
+ // \returns false on success and sets Result.
+ void handleNestedNameSpecifierLoc(NestedNameSpecifierLoc NameLoc) {
+ while (NameLoc) {
+ const NamespaceDecl *Decl =
+ NameLoc.getNestedNameSpecifier()->getAsNamespace();
+ setResult(Decl, NameLoc.getLocalBeginLoc(), NameLoc.getLocalEndLoc());
+ NameLoc = NameLoc.getPrefix();
+ }
+ }
+
+private:
+ // \brief Sets Result to Decl if the Point is within Start and End.
+ // \returns false on success.
+ bool setResult(const NamedDecl *Decl, SourceLocation Start,
+ SourceLocation End) {
+ if (!Decl)
+ return true;
+ if (Name.empty()) {
+ // Offset is used to find the declaration.
+ if (!Start.isValid() || !Start.isFileID() || !End.isValid() ||
+ !End.isFileID() || !isPointWithin(Start, End))
+ return true;
+ } else {
+ // Fully qualified name is used to find the declaration.
+ if (Name != Decl->getQualifiedNameAsString() &&
+ Name != "::" + Decl->getQualifiedNameAsString())
+ return true;
+ }
+ Result = Decl;
+ return false;
+ }
+
+ // \brief Sets Result to Decl if Point is within Loc and Loc + Offset.
+ // \returns false on success.
+ bool setResult(const NamedDecl *Decl, SourceLocation Loc, unsigned Offset) {
+ // FIXME: Add test for Offset == 0. Add test for Offset - 1 (vs -2 etc).
+ return Offset == 0 ||
+ setResult(Decl, Loc, Loc.getLocWithOffset(Offset - 1));
+ }
+
+ // \brief Determines if the Point is within Start and End.
+ bool isPointWithin(const SourceLocation Start, const SourceLocation End) {
+ // FIXME: Add tests for Point == End.
+ return Point == Start || Point == End ||
+ (Context.getSourceManager().isBeforeInTranslationUnit(Start,
+ Point) &&
+ Context.getSourceManager().isBeforeInTranslationUnit(Point, End));
+ }
+
+ const NamedDecl *Result;
+ const SourceLocation Point; // The location to find the NamedDecl.
+ const std::string Name;
+ const ASTContext &Context;
+};
+} // namespace
+
+const NamedDecl *getNamedDeclAt(const ASTContext &Context,
+ const SourceLocation Point) {
+ const SourceManager &SM = Context.getSourceManager();
+ NamedDeclFindingASTVisitor Visitor(Point, Context);
+
+ // Try to be clever about pruning down the number of top-level declarations we
+ // see. If both start and end is either before or after the point we're
+ // looking for the point cannot be inside of this decl. Don't even look at it.
+ for (auto *CurrDecl : Context.getTranslationUnitDecl()->decls()) {
+ SourceLocation StartLoc = CurrDecl->getLocStart();
+ SourceLocation EndLoc = CurrDecl->getLocEnd();
+ if (StartLoc.isValid() && EndLoc.isValid() &&
+ SM.isBeforeInTranslationUnit(StartLoc, Point) !=
+ SM.isBeforeInTranslationUnit(EndLoc, Point))
+ Visitor.TraverseDecl(CurrDecl);
+ }
+
+ NestedNameSpecifierLocFinder Finder(const_cast<ASTContext &>(Context));
+ for (const auto &Location : Finder.getNestedNameSpecifierLocations())
+ Visitor.handleNestedNameSpecifierLoc(Location);
+
+ return Visitor.getNamedDecl();
+}
+
+const NamedDecl *getNamedDeclFor(const ASTContext &Context,
+ const std::string &Name) {
+ NamedDeclFindingASTVisitor Visitor(Name, Context);
+ Visitor.TraverseDecl(Context.getTranslationUnitDecl());
+
+ return Visitor.getNamedDecl();
+}
+
+std::string getUSRForDecl(const Decl *Decl) {
+ llvm::SmallVector<char, 128> Buff;
+
+ // FIXME: Add test for the nullptr case.
+ if (Decl == nullptr || index::generateUSRForDecl(Decl, Buff))
+ return "";
+
+ return std::string(Buff.data(), Buff.size());
+}
+
+} // end namespace tooling
+} // end namespace clang
diff --git a/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp b/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
new file mode 100644
index 000000000000..2769802ad2bc
--- /dev/null
+++ b/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
@@ -0,0 +1,236 @@
+//===--- USRFindingAction.cpp - Clang refactoring library -----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Provides an action to find USR for the symbol at <offset>, as well as
+/// all additional USRs.
+///
+//===----------------------------------------------------------------------===//
+
+#include "clang/Tooling/Refactoring/Rename/USRFindingAction.h"
+#include "clang/AST/AST.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendAction.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Tooling/CommonOptionsParser.h"
+#include "clang/Tooling/Refactoring.h"
+#include "clang/Tooling/Refactoring/Rename/USRFinder.h"
+#include "clang/Tooling/Tooling.h"
+
+#include <algorithm>
+#include <set>
+#include <string>
+#include <vector>
+
+using namespace llvm;
+
+namespace clang {
+namespace tooling {
+
+namespace {
+// \brief NamedDeclFindingConsumer should delegate finding USRs of given Decl to
+// AdditionalUSRFinder. AdditionalUSRFinder adds USRs of ctor and dtor if given
+// Decl refers to class and adds USRs of all overridden methods if Decl refers
+// to virtual method.
+class AdditionalUSRFinder : public RecursiveASTVisitor<AdditionalUSRFinder> {
+public:
+ AdditionalUSRFinder(const Decl *FoundDecl, ASTContext &Context)
+ : FoundDecl(FoundDecl), Context(Context) {}
+
+ std::vector<std::string> Find() {
+ // Fill OverriddenMethods and PartialSpecs storages.
+ TraverseDecl(Context.getTranslationUnitDecl());
+ if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(FoundDecl)) {
+ addUSRsOfOverridenFunctions(MethodDecl);
+ for (const auto &OverriddenMethod : OverriddenMethods) {
+ if (checkIfOverriddenFunctionAscends(OverriddenMethod))
+ USRSet.insert(getUSRForDecl(OverriddenMethod));
+ }
+ } else if (const auto *RecordDecl = dyn_cast<CXXRecordDecl>(FoundDecl)) {
+ handleCXXRecordDecl(RecordDecl);
+ } else if (const auto *TemplateDecl =
+ dyn_cast<ClassTemplateDecl>(FoundDecl)) {
+ handleClassTemplateDecl(TemplateDecl);
+ } else {
+ USRSet.insert(getUSRForDecl(FoundDecl));
+ }
+ return std::vector<std::string>(USRSet.begin(), USRSet.end());
+ }
+
+ bool VisitCXXMethodDecl(const CXXMethodDecl *MethodDecl) {
+ if (MethodDecl->isVirtual())
+ OverriddenMethods.push_back(MethodDecl);
+ return true;
+ }
+
+ bool VisitClassTemplatePartialSpecializationDecl(
+ const ClassTemplatePartialSpecializationDecl *PartialSpec) {
+ PartialSpecs.push_back(PartialSpec);
+ return true;
+ }
+
+private:
+ void handleCXXRecordDecl(const CXXRecordDecl *RecordDecl) {
+ RecordDecl = RecordDecl->getDefinition();
+ if (const auto *ClassTemplateSpecDecl =
+ dyn_cast<ClassTemplateSpecializationDecl>(RecordDecl))
+ handleClassTemplateDecl(ClassTemplateSpecDecl->getSpecializedTemplate());
+ addUSRsOfCtorDtors(RecordDecl);
+ }
+
+ void handleClassTemplateDecl(const ClassTemplateDecl *TemplateDecl) {
+ for (const auto *Specialization : TemplateDecl->specializations())
+ addUSRsOfCtorDtors(Specialization);
+
+ for (const auto *PartialSpec : PartialSpecs) {
+ if (PartialSpec->getSpecializedTemplate() == TemplateDecl)
+ addUSRsOfCtorDtors(PartialSpec);
+ }
+ addUSRsOfCtorDtors(TemplateDecl->getTemplatedDecl());
+ }
+
+ void addUSRsOfCtorDtors(const CXXRecordDecl *RecordDecl) {
+ RecordDecl = RecordDecl->getDefinition();
+
+ // Skip if the CXXRecordDecl doesn't have definition.
+ if (!RecordDecl)
+ return;
+
+ for (const auto *CtorDecl : RecordDecl->ctors())
+ USRSet.insert(getUSRForDecl(CtorDecl));
+
+ USRSet.insert(getUSRForDecl(RecordDecl->getDestructor()));
+ USRSet.insert(getUSRForDecl(RecordDecl));
+ }
+
+ void addUSRsOfOverridenFunctions(const CXXMethodDecl *MethodDecl) {
+ USRSet.insert(getUSRForDecl(MethodDecl));
+ // Recursively visit each OverridenMethod.
+ for (const auto &OverriddenMethod : MethodDecl->overridden_methods())
+ addUSRsOfOverridenFunctions(OverriddenMethod);
+ }
+
+ bool checkIfOverriddenFunctionAscends(const CXXMethodDecl *MethodDecl) {
+ for (const auto &OverriddenMethod : MethodDecl->overridden_methods()) {
+ if (USRSet.find(getUSRForDecl(OverriddenMethod)) != USRSet.end())
+ return true;
+ return checkIfOverriddenFunctionAscends(OverriddenMethod);
+ }
+ return false;
+ }
+
+ const Decl *FoundDecl;
+ ASTContext &Context;
+ std::set<std::string> USRSet;
+ std::vector<const CXXMethodDecl *> OverriddenMethods;
+ std::vector<const ClassTemplatePartialSpecializationDecl *> PartialSpecs;
+};
+} // namespace
+
+class NamedDeclFindingConsumer : public ASTConsumer {
+public:
+ NamedDeclFindingConsumer(ArrayRef<unsigned> SymbolOffsets,
+ ArrayRef<std::string> QualifiedNames,
+ std::vector<std::string> &SpellingNames,
+ std::vector<std::vector<std::string>> &USRList,
+ bool Force, bool &ErrorOccurred)
+ : SymbolOffsets(SymbolOffsets), QualifiedNames(QualifiedNames),
+ SpellingNames(SpellingNames), USRList(USRList), Force(Force),
+ ErrorOccurred(ErrorOccurred) {}
+
+private:
+ bool FindSymbol(ASTContext &Context, const SourceManager &SourceMgr,
+ unsigned SymbolOffset, const std::string &QualifiedName) {
+ DiagnosticsEngine &Engine = Context.getDiagnostics();
+ const FileID MainFileID = SourceMgr.getMainFileID();
+
+ if (SymbolOffset >= SourceMgr.getFileIDSize(MainFileID)) {
+ ErrorOccurred = true;
+ unsigned InvalidOffset = Engine.getCustomDiagID(
+ DiagnosticsEngine::Error,
+ "SourceLocation in file %0 at offset %1 is invalid");
+ Engine.Report(SourceLocation(), InvalidOffset)
+ << SourceMgr.getFileEntryForID(MainFileID)->getName() << SymbolOffset;
+ return false;
+ }
+
+ const SourceLocation Point = SourceMgr.getLocForStartOfFile(MainFileID)
+ .getLocWithOffset(SymbolOffset);
+ const NamedDecl *FoundDecl = QualifiedName.empty()
+ ? getNamedDeclAt(Context, Point)
+ : getNamedDeclFor(Context, QualifiedName);
+
+ if (FoundDecl == nullptr) {
+ if (QualifiedName.empty()) {
+ FullSourceLoc FullLoc(Point, SourceMgr);
+ unsigned CouldNotFindSymbolAt = Engine.getCustomDiagID(
+ DiagnosticsEngine::Error,
+ "clang-rename could not find symbol (offset %0)");
+ Engine.Report(Point, CouldNotFindSymbolAt) << SymbolOffset;
+ ErrorOccurred = true;
+ return false;
+ }
+
+ if (Force)
+ return true;
+
+ unsigned CouldNotFindSymbolNamed = Engine.getCustomDiagID(
+ DiagnosticsEngine::Error, "clang-rename could not find symbol %0");
+ Engine.Report(CouldNotFindSymbolNamed) << QualifiedName;
+ ErrorOccurred = true;
+ return false;
+ }
+
+ // If FoundDecl is a constructor or destructor, we want to instead take
+ // the Decl of the corresponding class.
+ if (const auto *CtorDecl = dyn_cast<CXXConstructorDecl>(FoundDecl))
+ FoundDecl = CtorDecl->getParent();
+ else if (const auto *DtorDecl = dyn_cast<CXXDestructorDecl>(FoundDecl))
+ FoundDecl = DtorDecl->getParent();
+
+ SpellingNames.push_back(FoundDecl->getNameAsString());
+ AdditionalUSRFinder Finder(FoundDecl, Context);
+ USRList.push_back(Finder.Find());
+ return true;
+ }
+
+ void HandleTranslationUnit(ASTContext &Context) override {
+ const SourceManager &SourceMgr = Context.getSourceManager();
+ for (unsigned Offset : SymbolOffsets) {
+ if (!FindSymbol(Context, SourceMgr, Offset, ""))
+ return;
+ }
+ for (const std::string &QualifiedName : QualifiedNames) {
+ if (!FindSymbol(Context, SourceMgr, 0, QualifiedName))
+ return;
+ }
+ }
+
+ ArrayRef<unsigned> SymbolOffsets;
+ ArrayRef<std::string> QualifiedNames;
+ std::vector<std::string> &SpellingNames;
+ std::vector<std::vector<std::string>> &USRList;
+ bool Force;
+ bool &ErrorOccurred;
+};
+
+std::unique_ptr<ASTConsumer> USRFindingAction::newASTConsumer() {
+ return llvm::make_unique<NamedDeclFindingConsumer>(
+ SymbolOffsets, QualifiedNames, SpellingNames, USRList, Force,
+ ErrorOccurred);
+}
+
+} // end namespace tooling
+} // end namespace clang
diff --git a/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp b/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp
new file mode 100644
index 000000000000..934507fe6eae
--- /dev/null
+++ b/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp
@@ -0,0 +1,509 @@
+//===--- USRLocFinder.cpp - Clang refactoring library ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Methods for finding all instances of a USR. Our strategy is very
+/// simple; we just compare the USR at every relevant AST node with the one
+/// provided.
+///
+//===----------------------------------------------------------------------===//
+
+#include "clang/Tooling/Refactoring/Rename/USRLocFinder.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Tooling/Core/Lookup.h"
+#include "clang/Tooling/Refactoring/Rename/USRFinder.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
+#include <cstddef>
+#include <set>
+#include <string>
+#include <vector>
+
+using namespace llvm;
+
+namespace clang {
+namespace tooling {
+
+namespace {
+
+// \brief This visitor recursively searches for all instances of a USR in a
+// translation unit and stores them for later usage.
+class USRLocFindingASTVisitor
+ : public clang::RecursiveASTVisitor<USRLocFindingASTVisitor> {
+public:
+ explicit USRLocFindingASTVisitor(const std::vector<std::string> &USRs,
+ StringRef PrevName,
+ const ASTContext &Context)
+ : USRSet(USRs.begin(), USRs.end()), PrevName(PrevName), Context(Context) {
+ }
+
+ // Declaration visitors:
+
+ bool VisitCXXConstructorDecl(clang::CXXConstructorDecl *ConstructorDecl) {
+ for (const auto *Initializer : ConstructorDecl->inits()) {
+ // Ignore implicit initializers.
+ if (!Initializer->isWritten())
+ continue;
+ if (const clang::FieldDecl *FieldDecl = Initializer->getMember()) {
+ if (USRSet.find(getUSRForDecl(FieldDecl)) != USRSet.end())
+ LocationsFound.push_back(Initializer->getSourceLocation());
+ }
+ }
+ return true;
+ }
+
+ bool VisitNamedDecl(const NamedDecl *Decl) {
+ if (USRSet.find(getUSRForDecl(Decl)) != USRSet.end())
+ checkAndAddLocation(Decl->getLocation());
+ return true;
+ }
+
+ // Expression visitors:
+
+ bool VisitDeclRefExpr(const DeclRefExpr *Expr) {
+ const NamedDecl *Decl = Expr->getFoundDecl();
+
+ if (USRSet.find(getUSRForDecl(Decl)) != USRSet.end()) {
+ const SourceManager &Manager = Decl->getASTContext().getSourceManager();
+ SourceLocation Location = Manager.getSpellingLoc(Expr->getLocation());
+ checkAndAddLocation(Location);
+ }
+
+ return true;
+ }
+
+ bool VisitMemberExpr(const MemberExpr *Expr) {
+ const NamedDecl *Decl = Expr->getFoundDecl().getDecl();
+ if (USRSet.find(getUSRForDecl(Decl)) != USRSet.end()) {
+ const SourceManager &Manager = Decl->getASTContext().getSourceManager();
+ SourceLocation Location = Manager.getSpellingLoc(Expr->getMemberLoc());
+ checkAndAddLocation(Location);
+ }
+ return true;
+ }
+
+ // Other visitors:
+
+ bool VisitTypeLoc(const TypeLoc Loc) {
+ if (USRSet.find(getUSRForDecl(Loc.getType()->getAsCXXRecordDecl())) !=
+ USRSet.end())
+ checkAndAddLocation(Loc.getBeginLoc());
+ if (const auto *TemplateTypeParm =
+ dyn_cast<TemplateTypeParmType>(Loc.getType())) {
+ if (USRSet.find(getUSRForDecl(TemplateTypeParm->getDecl())) !=
+ USRSet.end())
+ checkAndAddLocation(Loc.getBeginLoc());
+ }
+ return true;
+ }
+
+ // Non-visitors:
+
+ // \brief Returns a list of unique locations. Duplicate or overlapping
+ // locations are erroneous and should be reported!
+ const std::vector<clang::SourceLocation> &getLocationsFound() const {
+ return LocationsFound;
+ }
+
+ // Namespace traversal:
+ void handleNestedNameSpecifierLoc(NestedNameSpecifierLoc NameLoc) {
+ while (NameLoc) {
+ const NamespaceDecl *Decl =
+ NameLoc.getNestedNameSpecifier()->getAsNamespace();
+ if (Decl && USRSet.find(getUSRForDecl(Decl)) != USRSet.end())
+ checkAndAddLocation(NameLoc.getLocalBeginLoc());
+ NameLoc = NameLoc.getPrefix();
+ }
+ }
+
+private:
+ void checkAndAddLocation(SourceLocation Loc) {
+ const SourceLocation BeginLoc = Loc;
+ const SourceLocation EndLoc = Lexer::getLocForEndOfToken(
+ BeginLoc, 0, Context.getSourceManager(), Context.getLangOpts());
+ StringRef TokenName =
+ Lexer::getSourceText(CharSourceRange::getTokenRange(BeginLoc, EndLoc),
+ Context.getSourceManager(), Context.getLangOpts());
+ size_t Offset = TokenName.find(PrevName);
+
+ // The token of the source location we find actually has the old
+ // name.
+ if (Offset != StringRef::npos)
+ LocationsFound.push_back(BeginLoc.getLocWithOffset(Offset));
+ }
+
+ const std::set<std::string> USRSet;
+ const std::string PrevName;
+ std::vector<clang::SourceLocation> LocationsFound;
+ const ASTContext &Context;
+};
+
+SourceLocation StartLocationForType(TypeLoc TL) {
+ // For elaborated types (e.g. `struct a::A`) we want the portion after the
+ // `struct` but including the namespace qualifier, `a::`.
+ if (auto ElaboratedTypeLoc = TL.getAs<clang::ElaboratedTypeLoc>()) {
+ NestedNameSpecifierLoc NestedNameSpecifier =
+ ElaboratedTypeLoc.getQualifierLoc();
+ if (NestedNameSpecifier.getNestedNameSpecifier())
+ return NestedNameSpecifier.getBeginLoc();
+ TL = TL.getNextTypeLoc();
+ }
+ return TL.getLocStart();
+}
+
+SourceLocation EndLocationForType(TypeLoc TL) {
+ // Dig past any namespace or keyword qualifications.
+ while (TL.getTypeLocClass() == TypeLoc::Elaborated ||
+ TL.getTypeLocClass() == TypeLoc::Qualified)
+ TL = TL.getNextTypeLoc();
+
+ // The location for template specializations (e.g. Foo<int>) includes the
+ // templated types in its location range. We want to restrict this to just
+ // before the `<` character.
+ if (TL.getTypeLocClass() == TypeLoc::TemplateSpecialization) {
+ return TL.castAs<TemplateSpecializationTypeLoc>()
+ .getLAngleLoc()
+ .getLocWithOffset(-1);
+ }
+ return TL.getEndLoc();
+}
+
+NestedNameSpecifier *GetNestedNameForType(TypeLoc TL) {
+ // Dig past any keyword qualifications.
+ while (TL.getTypeLocClass() == TypeLoc::Qualified)
+ TL = TL.getNextTypeLoc();
+
+ // For elaborated types (e.g. `struct a::A`) we want the portion after the
+ // `struct` but including the namespace qualifier, `a::`.
+ if (auto ElaboratedTypeLoc = TL.getAs<clang::ElaboratedTypeLoc>())
+ return ElaboratedTypeLoc.getQualifierLoc().getNestedNameSpecifier();
+ return nullptr;
+}
+
+// Find all locations identified by the given USRs for rename.
+//
+// This class will traverse the AST and find every AST node whose USR is in the
+// given USRs' set.
+class RenameLocFinder : public RecursiveASTVisitor<RenameLocFinder> {
+public:
+ RenameLocFinder(llvm::ArrayRef<std::string> USRs, ASTContext &Context)
+ : USRSet(USRs.begin(), USRs.end()), Context(Context) {}
+
+ // A structure records all information of a symbol reference being renamed.
+ // We try to add as few prefix qualifiers as possible.
+ struct RenameInfo {
+ // The begin location of a symbol being renamed.
+ SourceLocation Begin;
+ // The end location of a symbol being renamed.
+ SourceLocation End;
+ // The declaration of a symbol being renamed (can be nullptr).
+ const NamedDecl *FromDecl;
+ // The declaration in which the nested name is contained (can be nullptr).
+ const Decl *Context;
+ // The nested name being replaced (can be nullptr).
+ const NestedNameSpecifier *Specifier;
+ };
+
+ // FIXME: Currently, prefix qualifiers will be added to the renamed symbol
+ // definition (e.g. "class Foo {};" => "class b::Bar {};" when renaming
+ // "a::Foo" to "b::Bar").
+ // For renaming declarations/definitions, prefix qualifiers should be filtered
+ // out.
+ bool VisitNamedDecl(const NamedDecl *Decl) {
+ // UsingDecl has been handled in other place.
+ if (llvm::isa<UsingDecl>(Decl))
+ return true;
+
+ // DestructorDecl has been handled in Typeloc.
+ if (llvm::isa<CXXDestructorDecl>(Decl))
+ return true;
+
+ if (Decl->isImplicit())
+ return true;
+
+ if (isInUSRSet(Decl)) {
+ RenameInfo Info = {Decl->getLocation(), Decl->getLocation(), nullptr,
+ nullptr, nullptr};
+ RenameInfos.push_back(Info);
+ }
+ return true;
+ }
+
+ bool VisitDeclRefExpr(const DeclRefExpr *Expr) {
+ const NamedDecl *Decl = Expr->getFoundDecl();
+ if (isInUSRSet(Decl)) {
+ RenameInfo Info = {Expr->getSourceRange().getBegin(),
+ Expr->getSourceRange().getEnd(), Decl,
+ getClosestAncestorDecl(*Expr), Expr->getQualifier()};
+ RenameInfos.push_back(Info);
+ }
+
+ return true;
+ }
+
+ bool VisitUsingDecl(const UsingDecl *Using) {
+ for (const auto *UsingShadow : Using->shadows()) {
+ if (isInUSRSet(UsingShadow->getTargetDecl())) {
+ UsingDecls.push_back(Using);
+ break;
+ }
+ }
+ return true;
+ }
+
+ bool VisitNestedNameSpecifierLocations(NestedNameSpecifierLoc NestedLoc) {
+ if (!NestedLoc.getNestedNameSpecifier()->getAsType())
+ return true;
+ if (IsTypeAliasWhichWillBeRenamedElsewhere(NestedLoc.getTypeLoc()))
+ return true;
+
+ if (const auto *TargetDecl =
+ getSupportedDeclFromTypeLoc(NestedLoc.getTypeLoc())) {
+ if (isInUSRSet(TargetDecl)) {
+ RenameInfo Info = {NestedLoc.getBeginLoc(),
+ EndLocationForType(NestedLoc.getTypeLoc()),
+ TargetDecl, getClosestAncestorDecl(NestedLoc),
+ NestedLoc.getNestedNameSpecifier()->getPrefix()};
+ RenameInfos.push_back(Info);
+ }
+ }
+ return true;
+ }
+
+ bool VisitTypeLoc(TypeLoc Loc) {
+ if (IsTypeAliasWhichWillBeRenamedElsewhere(Loc))
+ return true;
+
+ auto Parents = Context.getParents(Loc);
+ TypeLoc ParentTypeLoc;
+ if (!Parents.empty()) {
+ // Handle cases of nested name specificier locations.
+ //
+ // The VisitNestedNameSpecifierLoc interface is not impelmented in
+ // RecursiveASTVisitor, we have to handle it explicitly.
+ if (const auto *NSL = Parents[0].get<NestedNameSpecifierLoc>()) {
+ VisitNestedNameSpecifierLocations(*NSL);
+ return true;
+ }
+
+ if (const auto *TL = Parents[0].get<TypeLoc>())
+ ParentTypeLoc = *TL;
+ }
+
+ // Handle the outermost TypeLoc which is directly linked to the interesting
+ // declaration and don't handle nested name specifier locations.
+ if (const auto *TargetDecl = getSupportedDeclFromTypeLoc(Loc)) {
+ if (isInUSRSet(TargetDecl)) {
+ // Only handle the outermost typeLoc.
+ //
+ // For a type like "a::Foo", there will be two typeLocs for it.
+ // One ElaboratedType, the other is RecordType:
+ //
+ // ElaboratedType 0x33b9390 'a::Foo' sugar
+ // `-RecordType 0x338fef0 'class a::Foo'
+ // `-CXXRecord 0x338fe58 'Foo'
+ //
+ // Skip if this is an inner typeLoc.
+ if (!ParentTypeLoc.isNull() &&
+ isInUSRSet(getSupportedDeclFromTypeLoc(ParentTypeLoc)))
+ return true;
+ RenameInfo Info = {StartLocationForType(Loc), EndLocationForType(Loc),
+ TargetDecl, getClosestAncestorDecl(Loc),
+ GetNestedNameForType(Loc)};
+ RenameInfos.push_back(Info);
+ return true;
+ }
+ }
+
+ // Handle specific template class specialiation cases.
+ if (const auto *TemplateSpecType =
+ dyn_cast<TemplateSpecializationType>(Loc.getType())) {
+ TypeLoc TargetLoc = Loc;
+ if (!ParentTypeLoc.isNull()) {
+ if (llvm::isa<ElaboratedType>(ParentTypeLoc.getType()))
+ TargetLoc = ParentTypeLoc;
+ }
+
+ if (isInUSRSet(TemplateSpecType->getTemplateName().getAsTemplateDecl())) {
+ TypeLoc TargetLoc = Loc;
+ // FIXME: Find a better way to handle this case.
+ // For the qualified template class specification type like
+ // "ns::Foo<int>" in "ns::Foo<int>& f();", we want the parent typeLoc
+ // (ElaboratedType) of the TemplateSpecializationType in order to
+ // catch the prefix qualifiers "ns::".
+ if (!ParentTypeLoc.isNull() &&
+ llvm::isa<ElaboratedType>(ParentTypeLoc.getType()))
+ TargetLoc = ParentTypeLoc;
+ RenameInfo Info = {
+ StartLocationForType(TargetLoc), EndLocationForType(TargetLoc),
+ TemplateSpecType->getTemplateName().getAsTemplateDecl(),
+ getClosestAncestorDecl(
+ ast_type_traits::DynTypedNode::create(TargetLoc)),
+ GetNestedNameForType(TargetLoc)};
+ RenameInfos.push_back(Info);
+ }
+ }
+ return true;
+ }
+
+ // Returns a list of RenameInfo.
+ const std::vector<RenameInfo> &getRenameInfos() const { return RenameInfos; }
+
+ // Returns a list of using declarations which are needed to update.
+ const std::vector<const UsingDecl *> &getUsingDecls() const {
+ return UsingDecls;
+ }
+
+private:
+ // FIXME: This method may not be suitable for renaming other types like alias
+ // types. Need to figure out a way to handle it.
+ bool IsTypeAliasWhichWillBeRenamedElsewhere(TypeLoc TL) const {
+ while (!TL.isNull()) {
+ // SubstTemplateTypeParm is the TypeLocation class for a substituted type
+ // inside a template expansion so we ignore these. For example:
+ //
+ // template<typename T> struct S {
+ // T t; // <-- this T becomes a TypeLoc(int) with class
+ // // SubstTemplateTypeParm when S<int> is instantiated
+ // }
+ if (TL.getTypeLocClass() == TypeLoc::SubstTemplateTypeParm)
+ return true;
+
+ // Typedef is the TypeLocation class for a type which is a typedef to the
+ // type we want to replace. We ignore the use of the typedef as we will
+ // replace the definition of it. For example:
+ //
+ // typedef int T;
+ // T a; // <--- This T is a TypeLoc(int) with class Typedef.
+ if (TL.getTypeLocClass() == TypeLoc::Typedef)
+ return true;
+ TL = TL.getNextTypeLoc();
+ }
+ return false;
+ }
+
+ // Get the supported declaration from a given typeLoc. If the declaration type
+ // is not supported, returns nullptr.
+ //
+ // FIXME: support more types, e.g. enum, type alias.
+ const NamedDecl *getSupportedDeclFromTypeLoc(TypeLoc Loc) {
+ if (const auto *RD = Loc.getType()->getAsCXXRecordDecl())
+ return RD;
+ return nullptr;
+ }
+
+ // Get the closest ancester which is a declaration of a given AST node.
+ template <typename ASTNodeType>
+ const Decl *getClosestAncestorDecl(const ASTNodeType &Node) {
+ auto Parents = Context.getParents(Node);
+ // FIXME: figure out how to handle it when there are multiple parents.
+ if (Parents.size() != 1)
+ return nullptr;
+ if (ast_type_traits::ASTNodeKind::getFromNodeKind<Decl>().isBaseOf(
+ Parents[0].getNodeKind()))
+ return Parents[0].template get<Decl>();
+ return getClosestAncestorDecl(Parents[0]);
+ }
+
+ // Get the parent typeLoc of a given typeLoc. If there is no such parent,
+ // return nullptr.
+ const TypeLoc *getParentTypeLoc(TypeLoc Loc) const {
+ auto Parents = Context.getParents(Loc);
+ // FIXME: figure out how to handle it when there are multiple parents.
+ if (Parents.size() != 1)
+ return nullptr;
+ return Parents[0].get<TypeLoc>();
+ }
+
+ // Check whether the USR of a given Decl is in the USRSet.
+ bool isInUSRSet(const Decl *Decl) const {
+ auto USR = getUSRForDecl(Decl);
+ if (USR.empty())
+ return false;
+ return llvm::is_contained(USRSet, USR);
+ }
+
+ const std::set<std::string> USRSet;
+ ASTContext &Context;
+ std::vector<RenameInfo> RenameInfos;
+ // Record all interested using declarations which contains the using-shadow
+ // declarations of the symbol declarations being renamed.
+ std::vector<const UsingDecl *> UsingDecls;
+};
+
+} // namespace
+
+std::vector<SourceLocation>
+getLocationsOfUSRs(const std::vector<std::string> &USRs, StringRef PrevName,
+ Decl *Decl) {
+ USRLocFindingASTVisitor Visitor(USRs, PrevName, Decl->getASTContext());
+ Visitor.TraverseDecl(Decl);
+ NestedNameSpecifierLocFinder Finder(Decl->getASTContext());
+
+ for (const auto &Location : Finder.getNestedNameSpecifierLocations())
+ Visitor.handleNestedNameSpecifierLoc(Location);
+
+ return Visitor.getLocationsFound();
+}
+
+std::vector<tooling::AtomicChange>
+createRenameAtomicChanges(llvm::ArrayRef<std::string> USRs,
+ llvm::StringRef NewName, Decl *TranslationUnitDecl) {
+ RenameLocFinder Finder(USRs, TranslationUnitDecl->getASTContext());
+ Finder.TraverseDecl(TranslationUnitDecl);
+
+ const SourceManager &SM =
+ TranslationUnitDecl->getASTContext().getSourceManager();
+
+ std::vector<tooling::AtomicChange> AtomicChanges;
+ auto Replace = [&](SourceLocation Start, SourceLocation End,
+ llvm::StringRef Text) {
+ tooling::AtomicChange ReplaceChange = tooling::AtomicChange(SM, Start);
+ llvm::Error Err = ReplaceChange.replace(
+ SM, CharSourceRange::getTokenRange(Start, End), Text);
+ if (Err) {
+ llvm::errs() << "Faile to add replacement to AtomicChange: "
+ << llvm::toString(std::move(Err)) << "\n";
+ return;
+ }
+ AtomicChanges.push_back(std::move(ReplaceChange));
+ };
+
+ for (const auto &RenameInfo : Finder.getRenameInfos()) {
+ std::string ReplacedName = NewName.str();
+ if (RenameInfo.FromDecl && RenameInfo.Context) {
+ if (!llvm::isa<clang::TranslationUnitDecl>(
+ RenameInfo.Context->getDeclContext())) {
+ ReplacedName = tooling::replaceNestedName(
+ RenameInfo.Specifier, RenameInfo.Context->getDeclContext(),
+ RenameInfo.FromDecl,
+ NewName.startswith("::") ? NewName.str() : ("::" + NewName).str());
+ }
+ }
+ // If the NewName contains leading "::", add it back.
+ if (NewName.startswith("::") && NewName.substr(2) == ReplacedName)
+ ReplacedName = NewName.str();
+ Replace(RenameInfo.Begin, RenameInfo.End, ReplacedName);
+ }
+
+ // Hanlde using declarations explicitly as "using a::Foo" don't trigger
+ // typeLoc for "a::Foo".
+ for (const auto *Using : Finder.getUsingDecls())
+ Replace(Using->getLocStart(), Using->getLocEnd(), "using " + NewName.str());
+
+ return AtomicChanges;
+}
+
+} // end namespace tooling
+} // end namespace clang
diff --git a/test/Analysis/malloc-overflow2.c b/test/Analysis/malloc-overflow2.c
index 2e1b1d4d2b24..7c580602e682 100644
--- a/test/Analysis/malloc-overflow2.c
+++ b/test/Analysis/malloc-overflow2.c
@@ -1,4 +1,5 @@
// RUN: %clang_analyze_cc1 -triple x86_64-unknown-unknown -analyzer-checker=alpha.security.MallocOverflow,unix -verify %s
+// RUN: %clang_analyze_cc1 -triple x86_64-unknown-unknown -analyzer-checker=alpha.security.MallocOverflow,unix,optin.portability -DPORTABILITY -verify %s
typedef __typeof__(sizeof(int)) size_t;
extern void *malloc(size_t);
@@ -32,5 +33,8 @@ static int table_build_1(struct table *t) {
}
void *f(int n) {
- return malloc(n * 0 * sizeof(int)); // expected-warning {{Call to 'malloc' has an allocation size of 0 bytes}}
+ return malloc(n * 0 * sizeof(int));
+#ifdef PORTABILITY
+ // expected-warning@-2{{Call to 'malloc' has an allocation size of 0 bytes}}
+#endif
}
diff --git a/test/Analysis/unix-fns.c b/test/Analysis/unix-fns.c
index 3eccd51d2c60..481f545e28bc 100644
--- a/test/Analysis/unix-fns.c
+++ b/test/Analysis/unix-fns.c
@@ -1,7 +1,7 @@
-// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,unix.API,osx.API %s -analyzer-store=region -analyzer-output=plist -analyzer-eagerly-assume -analyzer-config faux-bodies=true -analyzer-config path-diagnostics-alternate=false -fblocks -verify -o %t.plist
+// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,unix.API,osx.API,optin.portability %s -analyzer-store=region -analyzer-output=plist -analyzer-eagerly-assume -analyzer-config faux-bodies=true -analyzer-config path-diagnostics-alternate=false -fblocks -verify -o %t.plist
// RUN: FileCheck --input-file=%t.plist %s
// RUN: mkdir -p %t.dir
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.API,osx.API -analyzer-output=html -analyzer-config faux-bodies=true -fblocks -o %t.dir %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.API,osx.API,optin.portability -analyzer-output=html -analyzer-config faux-bodies=true -fblocks -o %t.dir %s
// RUN: rm -fR %t.dir
struct _opaque_pthread_once_t {
long __sig;
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 23d23bcddcc1..fa926c584f8e 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -47,6 +47,7 @@ list(APPEND CLANG_TEST_DEPS
clang-tblgen
clang-offload-bundler
clang-import-test
+ clang-rename
)
if(CLANG_ENABLE_STATIC_ANALYZER)
diff --git a/test/CodeGen/arm-execute-only.c b/test/CodeGen/arm-execute-only.c
new file mode 100644
index 000000000000..6d88ff611d68
--- /dev/null
+++ b/test/CodeGen/arm-execute-only.c
@@ -0,0 +1,78 @@
+// RUN: %clang -target armv6t2-eabi -### %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
+
+// RUN: %clang -target armv6t2-eabi -### -mexecute-only %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY
+
+// RUN: %clang -target armv6t2-eabi -### -mexecute-only -mno-execute-only %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
+
+// RUN: %clang -target armv7m-eabi -### %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
+
+// RUN: %clang -target armv7m-eabi -### -mexecute-only %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY
+
+// RUN: %clang -target armv7m-eabi -### -mexecute-only -mno-execute-only %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
+
+// RUN: %clang -target armv8m.base-eabi -### %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
+
+// RUN: %clang -target armv8m.base-eabi -### -mexecute-only %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY
+
+// RUN: %clang -target armv8m.base-eabi -### -mexecute-only -mno-execute-only %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
+
+// RUN: %clang -target armv8m.main-eabi -### %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
+
+// RUN: %clang -target armv8m.main-eabi -### -mexecute-only %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY
+
+// RUN: %clang -target armv8m.main-eabi -### -mexecute-only -mno-execute-only %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
+
+
+// -mpure-code flag for GCC compatibility
+// RUN: %clang -target armv6t2-eabi -### %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
+
+// RUN: %clang -target armv6t2-eabi -### -mpure-code %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY
+
+// RUN: %clang -target armv6t2-eabi -### -mpure-code -mno-pure-code %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
+
+// RUN: %clang -target armv7m-eabi -### %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
+
+// RUN: %clang -target armv7m-eabi -### -mpure-code %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY
+
+// RUN: %clang -target armv7m-eabi -### -mpure-code -mno-pure-code %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
+
+// RUN: %clang -target armv8m.base-eabi -### %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
+
+// RUN: %clang -target armv8m.base-eabi -### -mpure-code %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY
+
+// RUN: %clang -target armv8m.base-eabi -### -mpure-code -mno-pure-code %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
+
+// RUN: %clang -target armv8m.main-eabi -### %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
+
+// RUN: %clang -target armv8m.main-eabi -### -mpure-code %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY
+
+// RUN: %clang -target armv8m.main-eabi -### -mpure-code -mno-pure-code %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
+
+// CHECK-NO-EXECUTE-ONLY-NOT: "+execute-only"
+// CHECK-EXECUTE-ONLY: "+execute-only"
+
+void a() {}
diff --git a/test/CodeGen/arm-v8.1a-neon-intrinsics.c b/test/CodeGen/arm-v8.1a-neon-intrinsics.c
index 788883100456..6f5867b6c11f 100644
--- a/test/CodeGen/arm-v8.1a-neon-intrinsics.c
+++ b/test/CodeGen/arm-v8.1a-neon-intrinsics.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple armv8.1a-linux-gnu -target-feature +neon \
+// RUN: %clang_cc1 -triple armv8.1a-linux-gnu -target-abi apcs-gnu -target-feature +neon \
// RUN: -S -emit-llvm -o - %s \
// RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ARM
diff --git a/test/CodeGen/avx512f-builtins.c b/test/CodeGen/avx512f-builtins.c
index c66d83611ed1..c3356461a348 100644
--- a/test/CodeGen/avx512f-builtins.c
+++ b/test/CodeGen/avx512f-builtins.c
@@ -1,4 +1,7 @@
// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +avx512f -emit-llvm -o - -Wall -Werror | FileCheck %s
+
+// FIXME: It's wrong to check LLVM IR transformations from clang. This run should be removed and tests added to the appropriate LLVM pass.
+
// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +avx512f -O2 -emit-llvm -o - -Wall -Werror | FileCheck %s -check-prefix=O2
#include <immintrin.h>
@@ -8240,10 +8243,10 @@ __m128 test_mm_mask_move_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B)
{
// O2-LABEL: @test_mm_mask_move_ss
// O2: %[[M:.*]] = and i8 %__U, 1
- // O2: %[[M2:.*]] = icmp ne i8 %[[M]], 0
- // O2: %[[ELM1:.*]] = extractelement <4 x float> %__B, i32 0
- // O2: %[[ELM2:.*]] = extractelement <4 x float> %__W, i32 0
- // O2: %[[SEL:.*]] = select i1 %[[M2]], float %[[ELM1]], float %[[ELM2]]
+ // O2: %[[M2:.*]] = icmp
+ // O2: %[[ELM1:.*]] = extractelement <4 x float>
+ // O2: %[[ELM2:.*]] = extractelement <4 x float>
+ // O2: %[[SEL:.*]] = select i1 %[[M2]]
// O2: %[[RES:.*]] = insertelement <4 x float> %__A, float %[[SEL]], i32 0
// O2: ret <4 x float> %[[RES]]
return _mm_mask_move_ss ( __W, __U, __A, __B);
@@ -8253,9 +8256,9 @@ __m128 test_mm_maskz_move_ss (__mmask8 __U, __m128 __A, __m128 __B)
{
// O2-LABEL: @test_mm_maskz_move_ss
// O2: %[[M:.*]] = and i8 %__U, 1
- // O2: %[[M2:.*]] = icmp ne i8 %[[M]], 0
+ // O2: %[[M2:.*]] = icmp
// O2: %[[ELM1:.*]] = extractelement <4 x float> %__B, i32 0
- // O2: %[[SEL:.*]] = select i1 %[[M2]], float %[[ELM1]], float 0.0
+ // O2: %[[SEL:.*]] = select i1 %[[M2]]
// O2: %[[RES:.*]] = insertelement <4 x float> %__A, float %[[SEL]], i32 0
// O2: ret <4 x float> %[[RES]]
return _mm_maskz_move_ss (__U, __A, __B);
@@ -8265,10 +8268,10 @@ __m128d test_mm_mask_move_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __
{
// O2-LABEL: @test_mm_mask_move_sd
// O2: %[[M:.*]] = and i8 %__U, 1
- // O2: %[[M2:.*]] = icmp ne i8 %[[M]], 0
- // O2: %[[ELM1:.*]] = extractelement <2 x double> %__B, i32 0
- // O2: %[[ELM2:.*]] = extractelement <2 x double> %__W, i32 0
- // O2: %[[SEL:.*]] = select i1 %[[M2]], double %[[ELM1]], double %[[ELM2]]
+ // O2: %[[M2:.*]] = icmp
+ // O2: %[[ELM1:.*]] = extractelement <2 x double>
+ // O2: %[[ELM2:.*]] = extractelement <2 x double>
+ // O2: %[[SEL:.*]] = select i1 %[[M2]]
// O2: %[[RES:.*]] = insertelement <2 x double> %__A, double %[[SEL]], i32 0
// O2: ret <2 x double> %[[RES]]
return _mm_mask_move_sd ( __W, __U, __A, __B);
@@ -8278,9 +8281,9 @@ __m128d test_mm_maskz_move_sd (__mmask8 __U, __m128d __A, __m128d __B)
{
// O2-LABEL: @test_mm_maskz_move_sd
// O2: %[[M:.*]] = and i8 %__U, 1
- // O2: %[[M2:.*]] = icmp ne i8 %[[M]], 0
+ // O2: %[[M2:.*]] = icmp
// O2: %[[ELM1:.*]] = extractelement <2 x double> %__B, i32 0
- // O2: %[[SEL:.*]] = select i1 %[[M2]], double %[[ELM1]], double 0.0
+ // O2: %[[SEL:.*]] = select i1 %[[M2]]
// O2: %[[RES:.*]] = insertelement <2 x double> %__A, double %[[SEL]], i32 0
// O2: ret <2 x double> %[[RES]]
return _mm_maskz_move_sd (__U, __A, __B);
diff --git a/test/CodeGen/builtins-wasm.c b/test/CodeGen/builtins-wasm.c
index 0c0b87945d42..e0f72d2e5034 100644
--- a/test/CodeGen/builtins-wasm.c
+++ b/test/CodeGen/builtins-wasm.c
@@ -14,3 +14,15 @@ __SIZE_TYPE__ f2(__SIZE_TYPE__ delta) {
// WEBASSEMBLY32: call i32 @llvm.wasm.grow.memory.i32(i32 %{{.*}})
// WEBASSEMBLY64: call i64 @llvm.wasm.grow.memory.i64(i64 %{{.*}})
}
+
+void f3(unsigned int tag, void *obj) {
+ return __builtin_wasm_throw(tag, obj);
+// WEBASSEMBLY32: call void @llvm.wasm.throw(i32 %{{.*}}, i8* %{{.*}})
+// WEBASSEMBLY64: call void @llvm.wasm.throw(i32 %{{.*}}, i8* %{{.*}})
+}
+
+void f4() {
+ return __builtin_wasm_rethrow();
+// WEBASSEMBLY32: call void @llvm.wasm.rethrow()
+// WEBASSEMBLY64: call void @llvm.wasm.rethrow()
+}
diff --git a/test/CodeGen/lto-newpm-pipeline.c b/test/CodeGen/lto-newpm-pipeline.c
new file mode 100644
index 000000000000..10112da6d508
--- /dev/null
+++ b/test/CodeGen/lto-newpm-pipeline.c
@@ -0,0 +1,53 @@
+// REQUIRES: x86-registered-target
+
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm-bc -o /dev/null -fexperimental-new-pass-manager -fdebug-pass-manager -flto=full -O0 %s 2>&1 | FileCheck %s \
+// RUN: -check-prefix=CHECK-FULL-O0
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm-bc -o /dev/null -fexperimental-new-pass-manager -fdebug-pass-manager -flto=thin -O0 %s 2>&1 | FileCheck %s \
+// RUN: -check-prefix=CHECK-THIN-O0
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm-bc -o /dev/null -fexperimental-new-pass-manager -fdebug-pass-manager -flto=full -O1 %s 2>&1 | FileCheck %s \
+// RUN: -check-prefix=CHECK-FULL-OPTIMIZED
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm-bc -o /dev/null -fexperimental-new-pass-manager -fdebug-pass-manager -flto=thin -O1 %s 2>&1 | FileCheck %s \
+// RUN: -check-prefix=CHECK-THIN-OPTIMIZED
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm-bc -o /dev/null -fexperimental-new-pass-manager -fdebug-pass-manager -flto=full -O2 %s 2>&1 | FileCheck %s \
+// RUN: -check-prefix=CHECK-FULL-OPTIMIZED
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm-bc -o /dev/null -fexperimental-new-pass-manager -fdebug-pass-manager -flto=thin -O2 %s 2>&1 | FileCheck %s \
+// RUN: -check-prefix=CHECK-THIN-OPTIMIZED
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm-bc -o /dev/null -fexperimental-new-pass-manager -fdebug-pass-manager -flto=full -O3 %s 2>&1 | FileCheck %s \
+// RUN: -check-prefix=CHECK-FULL-OPTIMIZED
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm-bc -o /dev/null -fexperimental-new-pass-manager -fdebug-pass-manager -flto=thin -O3 %s 2>&1 | FileCheck %s \
+// RUN: -check-prefix=CHECK-THIN-OPTIMIZED
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm-bc -o /dev/null -fexperimental-new-pass-manager -fdebug-pass-manager -flto=full -Os %s 2>&1 | FileCheck %s \
+// RUN: -check-prefix=CHECK-FULL-OPTIMIZED
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm-bc -o /dev/null -fexperimental-new-pass-manager -fdebug-pass-manager -flto=thin -Os %s 2>&1 | FileCheck %s \
+// RUN: -check-prefix=CHECK-THIN-OPTIMIZED
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm-bc -o /dev/null -fexperimental-new-pass-manager -fdebug-pass-manager -flto=full -Oz %s 2>&1 | FileCheck %s \
+// RUN: -check-prefix=CHECK-FULL-OPTIMIZED
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm-bc -o /dev/null -fexperimental-new-pass-manager -fdebug-pass-manager -flto=thin -Oz %s 2>&1 | FileCheck %s \
+// RUN: -check-prefix=CHECK-THIN-OPTIMIZED
+
+// CHECK-FULL-O0: Starting llvm::Module pass manager run.
+// CHECK-FULL-O0: Running pass: AlwaysInlinerPass
+// CHECK-FULL-O0-NEXT: Running pass: BitcodeWriterPass
+// CHECK-FULL-O0: Finished llvm::Module pass manager run.
+
+// CHECK-THIN-O0: Starting llvm::Module pass manager run.
+// CHECK-THIN-O0: Running pass: AlwaysInlinerPass
+// CHECK-THIN-O0-NEXT: Running pass: NameAnonGlobalPass
+// CHECK-THIN-O0-NEXT: Running pass: ThinLTOBitcodeWriterPass
+// CHECK-THIN-O0: Finished llvm::Module pass manager run.
+
+// TODO: The LTO pre-link pipeline currently invokes
+// buildPerModuleDefaultPipeline(), which contains LoopVectorizePass.
+// This may change as the pipeline gets implemented.
+// CHECK-FULL-OPTIMIZED: Starting llvm::Function pass manager run.
+// CHECK-FULL-OPTIMIZED: Running pass: LoopVectorizePass
+// CHECK-FULL-OPTIMIZED: Running pass: BitcodeWriterPass
+
+// The ThinLTO pre-link pipeline shouldn't contain passes like
+// LoopVectorizePass.
+// CHECK-THIN-OPTIMIZED: Starting llvm::Function pass manager run.
+// CHECK-THIN-OPTIMIZED-NOT: Running pass: LoopVectorizePass
+// CHECK-THIN-OPTIMIZED: Running pass: NameAnonGlobalPass
+// CHECK-THIN-OPTIMIZED: Running pass: ThinLTOBitcodeWriterPass
+
+void Foo() {}
diff --git a/test/CodeGen/mangle-ms.c b/test/CodeGen/mangle-ms.c
index 0ad43d5e06c2..042c72e6d794 100644
--- a/test/CodeGen/mangle-ms.c
+++ b/test/CodeGen/mangle-ms.c
@@ -2,3 +2,12 @@
// CHECK: define void @"\01?f@@$$J0YAXP6AX@Z@Z"
__attribute__((overloadable)) void f(void (*x)()) {}
+
+// CHECK: define void @f
+void f(void (*x)(int)) {}
+
+// CHECK: define void @g
+void g(void (*x)(int)) {}
+
+// CHECK: define void @"\01?g@@$$J0YAXP6AX@Z@Z"
+__attribute__((overloadable)) void g(void (*x)()) {}
diff --git a/test/CodeGen/mangle.c b/test/CodeGen/mangle.c
index 46ef512f6950..f94139bc5e3c 100644
--- a/test/CodeGen/mangle.c
+++ b/test/CodeGen/mangle.c
@@ -9,6 +9,10 @@ void __attribute__((__overloadable__)) f0(int a) {}
// CHECK: @_Z2f0l
void __attribute__((__overloadable__)) f0(long b) {}
+// Unless it's unmarked.
+// CHECK: @f0
+void f0(float b) {}
+
// CHECK: @bar
// These should get merged.
diff --git a/test/CodeGen/named_reg_global.c b/test/CodeGen/named_reg_global.c
index 1da625746891..232b74de1cab 100644
--- a/test/CodeGen/named_reg_global.c
+++ b/test/CodeGen/named_reg_global.c
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -triple x86_64-linux-gnu -S -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-X86-64
// RUN: %clang_cc1 -triple arm64-linux-gnu -S -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ARM
-// RUN: %clang_cc1 -triple armv7-linux-gnu -S -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ARM
+// RUN: %clang_cc1 -triple armv7-linux-gnu -target-abi apcs-gnu -S -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ARM
// CHECK-NOT: @sp = common global
diff --git a/test/CodeGen/neon-immediate-ubsan.c b/test/CodeGen/neon-immediate-ubsan.c
index c3e1ce23301d..aacf76a6338b 100644
--- a/test/CodeGen/neon-immediate-ubsan.c
+++ b/test/CodeGen/neon-immediate-ubsan.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple armv7s-linux-gnu -emit-llvm -o - %s \
+// RUN: %clang_cc1 -triple armv7s-linux-gnu -target-abi apcs-gnu -emit-llvm -o - %s \
// RUN: -target-feature +neon -target-cpu cortex-a8 \
// RUN: -fsanitize=signed-integer-overflow \
// RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=ARMV7
diff --git a/test/CodeGen/pgo-sample-thinlto-summary.c b/test/CodeGen/pgo-sample-thinlto-summary.c
index 7782aeb76616..51c8faa6be6d 100644
--- a/test/CodeGen/pgo-sample-thinlto-summary.c
+++ b/test/CodeGen/pgo-sample-thinlto-summary.c
@@ -1,5 +1,9 @@
-// RUN: %clang_cc1 -O2 -fprofile-sample-use=%S/Inputs/pgo-sample-thinlto-summary.prof %s -emit-llvm -o - 2>&1 | FileCheck %s -check-prefix=O2
+// RUN: %clang_cc1 -O2 -fprofile-sample-use=%S/Inputs/pgo-sample-thinlto-summary.prof %s -emit-llvm -o - 2>&1 | FileCheck %s -check-prefix=SAMPLEPGO
// RUN: %clang_cc1 -O2 -fprofile-sample-use=%S/Inputs/pgo-sample-thinlto-summary.prof %s -emit-llvm -flto=thin -o - 2>&1 | FileCheck %s -check-prefix=THINLTO
+// RUN: %clang_cc1 -O2 -fexperimental-new-pass-manager -fprofile-sample-use=%S/Inputs/pgo-sample-thinlto-summary.prof %s -emit-llvm -o - 2>&1 | FileCheck %s -check-prefix=SAMPLEPGO
+// FIXME: Run the following command once LTOPreLinkDefaultPipeline is
+// customized.
+// %clang_cc1 -O2 -fexperimental-new-pass-manager -fprofile-sample-use=%S/Inputs/pgo-sample-thinlto-summary.prof %s -emit-llvm -flto=thin -o - 2>&1 | FileCheck %s -check-prefix=THINLTO
// Checks if hot call is inlined by normal compile, but not inlined by
// thinlto compile.
@@ -11,9 +15,9 @@ void foo(int n) {
g += baz(i);
}
-// O2-LABEL: define void @bar
+// SAMPLEPGO-LABEL: define void @bar
// THINLTO-LABEL: define void @bar
-// O2-NOT: call{{.*}}foo
+// SAMPLEPGO-NOT: call{{.*}}foo
// THINLTO: call{{.*}}foo
void bar(int n) {
for (int i = 0; i < n; i++)
@@ -21,10 +25,10 @@ void bar(int n) {
}
// Checks if loop unroll is invoked by normal compile, but not thinlto compile.
-// O2-LABEL: define void @unroll
+// SAMPLEPGO-LABEL: define void @unroll
// THINLTO-LABEL: define void @unroll
-// O2: call{{.*}}baz
-// O2: call{{.*}}baz
+// SAMPLEPGO: call{{.*}}baz
+// SAMPLEPGO: call{{.*}}baz
// THINLTO: call{{.*}}baz
// THINLTO-NOT: call{{.*}}baz
void unroll() {
@@ -32,11 +36,13 @@ void unroll() {
baz(i);
}
-// Check that icp is not invoked (both -O2 and ThinLTO).
-// O2-LABEL: define void @icp
+// Checks that icp is not invoked for ThinLTO, but invoked for normal samplepgo.
+// SAMPLEPGO-LABEL: define void @icp
// THINLTO-LABEL: define void @icp
-// O2-NOT: if.true.direct_targ
-// ThinLTO-NOT: if.true.direct_targ
+// SAMPLEPGO: if.true.direct_targ
+// FIXME: the following condition needs to be reversed once
+// LTOPreLinkDefaultPipeline is customized.
+// THINLTO-NOT: if.true.direct_targ
void icp(void (*p)()) {
p();
}
diff --git a/test/CodeGen/xray-attributes-supported.cpp b/test/CodeGen/xray-attributes-supported.cpp
index 860efb276f69..21a5dde53a05 100644
--- a/test/CodeGen/xray-attributes-supported.cpp
+++ b/test/CodeGen/xray-attributes-supported.cpp
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 %s -fxray-instrument -std=c++11 -x c++ -emit-llvm -o - -triple x86_64-unknown-linux-gnu | FileCheck %s
-// RUN: %clang_cc1 %s -fxray-instrument -std=c++11 -x c++ -emit-llvm -o - -triple arm-unknown-linux-gnu | FileCheck %s
+// RUN: %clang_cc1 %s -fxray-instrument -std=c++11 -x c++ -emit-llvm -o - -triple arm-unknown-linux-gnu -target-abi apcs-gnu | FileCheck %s
// RUN: %clang_cc1 %s -fxray-instrument -std=c++11 -x c++ -emit-llvm -o - -triple mips-unknown-linux-gnu | FileCheck %s
// RUN: %clang_cc1 %s -fxray-instrument -std=c++11 -x c++ -emit-llvm -o - -triple mipsel-unknown-linux-gnu | FileCheck %s
// RUN: %clang_cc1 %s -fxray-instrument -std=c++11 -x c++ -emit-llvm -o - -triple mips64-unknown-linux-gnu | FileCheck %s
diff --git a/test/CodeGenCXX/dllexport-dtor-thunks.cpp b/test/CodeGenCXX/dllexport-dtor-thunks.cpp
new file mode 100644
index 000000000000..52f9901620fa
--- /dev/null
+++ b/test/CodeGenCXX/dllexport-dtor-thunks.cpp
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -mconstructor-aliases -fms-extensions %s -emit-llvm -o - -triple x86_64-windows-msvc | FileCheck %s
+
+struct __declspec(dllexport) A { virtual ~A(); };
+struct __declspec(dllexport) B { virtual ~B(); };
+struct __declspec(dllexport) C : A, B { virtual ~C(); };
+C::~C() {}
+
+// This thunk should *not* be dllexport.
+// CHECK: define linkonce_odr i8* @"\01??_EC@@W7EAAPEAXI@Z"
+// CHECK: define dllexport void @"\01??1C@@UEAA@XZ"
diff --git a/test/CodeGenCXX/mangle-ms.cpp b/test/CodeGenCXX/mangle-ms.cpp
index ee0f50e5e2d3..7e2f17f27a96 100644
--- a/test/CodeGenCXX/mangle-ms.cpp
+++ b/test/CodeGenCXX/mangle-ms.cpp
@@ -399,6 +399,13 @@ template void fn_tmpl<extern_c_func>();
extern "C" void __attribute__((overloadable)) overloaded_fn() {}
// CHECK-DAG: @"\01?overloaded_fn@@$$J0YAXXZ"
+extern "C" void overloaded_fn2() {}
+// CHECK-DAG: @overloaded_fn2
+//
+extern "C" void __attribute__((overloadable)) overloaded_fn3();
+extern "C" void overloaded_fn3() {}
+// CHECK-DAG: @overloaded_fn3
+
namespace UnnamedType {
struct S {
typedef struct {} *T1[1];
diff --git a/test/CodeGenCXX/msabi-blocks.cpp b/test/CodeGenCXX/msabi-blocks.cpp
new file mode 100644
index 000000000000..bee59d9ed535
--- /dev/null
+++ b/test/CodeGenCXX/msabi-blocks.cpp
@@ -0,0 +1,113 @@
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -std=c++11 -fblocks -S -o - -emit-llvm %s | FileCheck %s -check-prefix CHECK-X86
+// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -std=c++11 -fblocks -S -o - -emit-llvm %s | FileCheck %s -check-prefix CHECK-X64
+
+extern int e(void);
+
+void (^b)() = ^{
+ static int i = 0;
+};
+
+// CHECK-X86-DAG: @"\01?i@?1??_block_invoke@@YAXPAU__block_literal@@@Z@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"\01?i@?1??_block_invoke@@YAXPEAU__block_literal@@@Z@4HA" ={{.*}} global i32 0
+
+void f(void) {
+ static int i = 0;
+ ^{ static int i = e(); }();
+
+// CHECK-X86-DAG: @"\01?i@?1??_block_invoke_1@@YAXPAU__block_literal_1@@@Z?1??f@@YAXXZ@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"\01?i@?1??_block_invoke_1@@YAXPEAU__block_literal_1@@@Z?1??f@@YAXXZ@4HA" ={{.*}} global i32 0
+
+ ^{ static int i = e(); }();
+
+// CHECK-X86-DAG: @"\01?i@?1??_block_invoke_2@@YAXPAU__block_literal_2@@@Z?1??f@@YAXXZ@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"\01?i@?1??_block_invoke_2@@YAXPEAU__block_literal_2@@@Z?1??f@@YAXXZ@4HA" ={{.*}} global i32 0
+
+ ^{ ^{ static int i = e(); }(); }();
+
+// CHECK-X86-DAG: @"\01?i@?1??_block_invoke_3@@YAXPAU__block_literal_3@@@Z?1??_block_invoke_4@@YAXPAU__block_literal_4@@@Z?1??f@@YAXXZ@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"\01?i@?1??_block_invoke_3@@YAXPEAU__block_literal_3@@@Z?1??_block_invoke_4@@YAXPEAU__block_literal_4@@@Z?1??f@@YAXXZ@4HA" ={{.*}} global i32 0
+}
+
+
+template <typename>
+void g(void) {
+ ^{ static int i = e(); }();
+}
+
+template void g<char>(void);
+
+// CHECK-X86-DAG: @"\01?i@?2??_block_invoke_1@@YAXPAU__block_literal_1@@@Z?2???$g@D@@YAXXZ@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"\01?i@?2??_block_invoke_1@@YAXPEAU__block_literal_1@@@Z?2???$g@D@@YAXXZ@4HA" ={{.*}} global i32 0
+
+template void g<int>(void);
+
+// CHECK-X86-DAG: @"\01?i@?2??_block_invoke_1@@YAXPAU__block_literal_1@@@Z?2???$g@H@@YAXXZ@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"\01?i@?2??_block_invoke_1@@YAXPEAU__block_literal_1@@@Z?2???$g@H@@YAXXZ@4HA" ={{.*}} global i32 0
+
+inline void h(void) {
+ ^{ static int i = e(); }();
+}
+
+// CHECK-X86-DAG: @"\01?i@?2??_block_invoke_1@@YAXPAU__block_literal_1@@@Z?2??h@@YAXXZ@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"\01?i@?2??_block_invoke_1@@YAXPEAU__block_literal_1@@@Z?2??h@@YAXXZ@4HA" ={{.*}} global i32 0
+
+struct s {
+ int i = ^{ static int i = e(); return ++i; }();
+
+// CHECK-X86-DAG: @"\01?i@?0??_block_invoke_1@0s@@YAXPAU__block_literal_1@@@Z@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"\01?i@?0??_block_invoke_1@0s@@YAXPEAU__block_literal_1@@@Z@4HA" ={{.*}} global i32 0
+
+ int j = ^{ static int i = e(); return ++i; }();
+
+// CHECK-X86-DAG: @"\01?i@?0??_block_invoke_1@j@s@@YAXPAU__block_literal_1@@@Z@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"\01?i@?0??_block_invoke_1@j@s@@YAXPEAU__block_literal_1@@@Z@4HA" ={{.*}} global i32 0
+
+ void m(int i = ^{ static int i = e(); return ++i; }(),
+ int j = ^{ static int i = e(); return ++i; }()) {}
+
+// CHECK-X86-DAG: @"\01?i@?0??_block_invoke_1_1@@YAXPAU__block_literal_1_1@@@Z?0??m@s@@QAEXHH@Z@4HA" ={{.*}} global i32 0
+// CHECK-X86-DAG: @"\01?i@?0??_block_invoke_1_2@@YAXPAU__block_literal_1_2@@@Z?0??m@s@@QAEXHH@Z@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"\01?i@?0??_block_invoke_1_1@@YAXPEAU__block_literal_1_1@@@Z?0??m@s@@QEAAXHH@Z@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"\01?i@?0??_block_invoke_1_2@@YAXPEAU__block_literal_1_2@@@Z?0??m@s@@QEAAXHH@Z@4HA" ={{.*}} global i32 0
+
+ void n(int = ^{ static int i = e(); return ++i; }(),
+ int = ^{ static int i = e(); return ++i; }()) {}
+
+// CHECK-X86-DAG: @"\01?i@?0??_block_invoke_1_1@@YAXPAU__block_literal_1_1@@@Z?0??n@s@@QAEXHH@Z@4HA" ={{.*}} global i32 0
+// CHECK-X86-DAG: @"\01?i@?0??_block_invoke_1_2@@YAXPAU__block_literal_1_2@@@Z?0??n@s@@QAEXHH@Z@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"\01?i@?0??_block_invoke_1_1@@YAXPEAU__block_literal_1_1@@@Z?0??n@s@@QEAAXHH@Z@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"\01?i@?0??_block_invoke_1_2@@YAXPEAU__block_literal_1_2@@@Z?0??n@s@@QEAAXHH@Z@4HA" ={{.*}} global i32 0
+
+};
+
+struct t {
+ struct u {
+ int i = ^{ static int i = e(); return ++i; }();
+
+// CHECK-X86-DAG: @"\01?i@?0??_block_invoke_1@0u@t@@YAXPAU__block_literal_1@@@Z@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"\01?i@?0??_block_invoke_1@0u@t@@YAXPEAU__block_literal_1@@@Z@4HA" ={{.*}} global i32 0
+
+ };
+};
+
+void j(void) {
+ h();
+ struct s s;
+ s.m();
+ s.n();
+ struct t::u t;
+}
+
+#if 0
+template <typename T>
+struct v {
+ static T i;
+};
+
+template <typename T>
+T v<T>::i = ^{ static T i = T(); return i; }();
+
+template class v<char>;
+template class v<int>;
+#endif
+
diff --git a/test/CodeGenObjC/ivar-type-encoding.m b/test/CodeGenObjC/ivar-type-encoding.m
index ffa5e0d7af0d..2fd962cf07bb 100644
--- a/test/CodeGenObjC/ivar-type-encoding.m
+++ b/test/CodeGenObjC/ivar-type-encoding.m
@@ -33,3 +33,19 @@ int main() {
// CHECK: @1 = private unnamed_addr constant [12 x i8] c"@\22NSString\22\00"
// CHECK: @2 = private unnamed_addr constant [9 x i8] c"_intIvar\00"
// CHECK: @3 = private unnamed_addr constant [2 x i8] c"i\00"
+
+@interface Class1 {
+ int : 3;
+ short : 2;
+ long long ll;
+ char : 1;
+}
+@end
+
+@implementation Class1
+@end
+
+// CHECK: @{{.*}} = private unnamed_addr constant [5 x i8] c"b0i3\00"
+// CHECK: @{{.*}} = private unnamed_addr constant [5 x i8] c"b3s2\00"
+// CHECK: @{{.*}} = private unnamed_addr constant [2 x i8] c"q\00"
+// CHECK: @{{.*}} = private unnamed_addr constant [{{7|6}} x i8] c"b{{128|96}}c1\00"
diff --git a/test/CodeGenObjC/parameterized_classes.m b/test/CodeGenObjC/parameterized_classes.m
index 8fe5c52b8d39..34aca35af313 100644
--- a/test/CodeGenObjC/parameterized_classes.m
+++ b/test/CodeGenObjC/parameterized_classes.m
@@ -96,3 +96,31 @@ void blockTest(NSMutableArray<void (^)(void)> *array, NSString *name) {
_destination = a;
}
@end
+
+// CHECK-LABEL: define internal void @"\01-[C0 foo1]"(
+// CHECK: {{.*}} = alloca
+// CHECK: {{.*}} = alloca
+// CHECK: %[[D:.*]] = alloca %[[TY:.*]]*
+// CHECK: %[[TEMP:.*]] = alloca %[[TY]]*
+// CHECK: %[[V4:.*]] = load %[[TY]]*, %[[TY]]** %[[D]]
+// CHECK: store %[[TY]]* %[[V4]], %[[TY]]** %[[TEMP]]
+// CHECK: %[[V7:.*]] = bitcast %[[TY]]** %[[TEMP]] to i8**
+// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i8**)*)(i8* %{{.*}}, i8* %{{.*}}, i8** %[[V7]])
+
+@interface P0<ObjectType> : NSObject
+- (void)m0:(ObjectType *)first;
+@end
+
+@interface C0 : NSObject
+-(void)foo1;
+@end
+
+@implementation C0 {
+ P0<NSString *> *x;
+}
+
+-(void)foo1 {
+ NSString *d;
+ [x m0:&d];
+}
+@end
diff --git a/test/CodeGenObjC/protocol-comdat.m b/test/CodeGenObjC/protocol-comdat.m
index 65e1b9fa2c82..a19ba8cf35dc 100644
--- a/test/CodeGenObjC/protocol-comdat.m
+++ b/test/CodeGenObjC/protocol-comdat.m
@@ -4,6 +4,9 @@
- (void) method;
@end
+@protocol Q;
+@protocol R;
+
@interface I<P>
@end
@@ -11,9 +14,14 @@
- (void) method { }
@end
+_Bool f(void) {
+ return @protocol(Q) == @protocol(R);
+}
// CHECK: $"\01l_OBJC_PROTOCOL_$_P" = comdat any
// CHECK: $"\01l_OBJC_LABEL_PROTOCOL_$_P" = comdat any
+// CHECK: $"\01l_OBJC_PROTOCOL_REFERENCE_$_Q" = comdat any
+// CHECK: $"\01l_OBJC_PROTOCOL_REFERENCE_$_R" = comdat any
// CHECK: @"\01l_OBJC_PROTOCOL_$_P" = {{.*}}, comdat
// CHECK: @"\01l_OBJC_LABEL_PROTOCOL_$_P" = {{.*}}, comdat
diff --git a/test/CodeGenObjC/stret-1.m b/test/CodeGenObjC/stret-1.m
index a7bcdda48b14..2314d5a9ecf5 100644
--- a/test/CodeGenObjC/stret-1.m
+++ b/test/CodeGenObjC/stret-1.m
@@ -12,11 +12,20 @@ struct stret one = {{1}};
int main(int argc, const char **argv)
{
- [(id)(argc&~255) method];
+ struct stret s;
+ s = [(id)(argc&~255) method];
// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (%struct.stret*, i8*, i8*)*)(%struct.stret* sret [[T0:%[^,]+]]
// CHECK: [[T0P:%.*]] = bitcast %struct.stret* [[T0]] to i8*
// CHECK: call void @llvm.memset.p0i8.i64(i8* [[T0P]], i8 0, i64 400, i32 4, i1 false)
+ s = [Test method];
+ // CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (%struct.stret*, i8*, i8*)*)(%struct.stret* sret [[T1:%[^,]+]]
+ // CHECK-NOT: call void @llvm.memset.p0i8.i64(
+
+ [(id)(argc&~255) method];
+ // CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (%struct.stret*, i8*, i8*)*)(%struct.stret* sret [[T1:%[^,]+]]
+ // CHECK-NOT: call void @llvm.memset.p0i8.i64(
+
[Test method];
// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (%struct.stret*, i8*, i8*)*)(%struct.stret* sret [[T1:%[^,]+]]
// CHECK-NOT: call void @llvm.memset.p0i8.i64(
diff --git a/test/CodeGenObjC/stret-lifetime.m b/test/CodeGenObjC/stret-lifetime.m
new file mode 100644
index 000000000000..d81ef34aeed4
--- /dev/null
+++ b/test/CodeGenObjC/stret-lifetime.m
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -triple arm64-apple-darwin -S -emit-llvm -o - -O2 -disable-llvm-passes %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -S -emit-llvm -o - -O2 -disable-llvm-passes %s | FileCheck %s
+// RUN: %clang_cc1 -triple arm64-apple-darwin -fobjc-arc -S -emit-llvm -o - -O2 -disable-llvm-passes %s | FileCheck %s --check-prefixes=CHECK,ARC
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-arc -S -emit-llvm -o - -O2 -disable-llvm-passes %s | FileCheck %s --check-prefixes=CHECK,ARC
+
+struct stret { int x[100]; };
+struct stret one = {{1}};
+
+@interface Test
++(struct stret) method;
++(struct stret) methodConsuming:(id __attribute__((ns_consumed)))consumed;
+@end
+
+void foo(id o, id p) {
+ [o method];
+ // CHECK: @llvm.lifetime.start
+ // CHECK: call void bitcast {{.*}} @objc_msgSend
+ // CHECK: @llvm.lifetime.end
+ // CHECK-NOT: call void @llvm.memset
+
+ [o methodConsuming:p];
+ // ARC: [[T0:%.*]] = icmp eq i8*
+ // ARC: br i1 [[T0]]
+
+ // CHECK: @llvm.lifetime.start
+ // CHECK: call void bitcast {{.*}} @objc_msgSend
+ // CHECK: @llvm.lifetime.end
+ // ARC: br label
+
+ // ARC: call void @objc_release
+ // ARC: br label
+
+ // CHECK-NOT: call void @llvm.memset
+}
diff --git a/test/CodeGenObjCXX/arc-indirect.mm b/test/CodeGenObjCXX/arc-indirect.mm
new file mode 100644
index 000000000000..6982bac04118
--- /dev/null
+++ b/test/CodeGenObjCXX/arc-indirect.mm
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -std=c++11 -triple i686-unknown-windows-msvc -fobjc-runtime=gnustep -fobjc-arc -Wno-objc-root-class -emit-llvm -o - %s | FileCheck -check-prefixes CHECK,CHECK-GNUSTEP %s
+// RUN: %clang_cc1 -std=c++11 -triple i686-unknown-windows-msvc -fobjc-runtime=macosx -fobjc-arc -Wno-objc-root-class -emit-llvm -o - %s | FileCheck -check-prefixes CHECK,CHECK-DARWIN %s
+// RUN: %clang_cc1 -std=c++11 -triple i686-unknown-windows-msvc -fobjc-runtime=ios -fobjc-arc -Wno-objc-root-class -emit-llvm -o - %s | FileCheck -check-prefixes CHECK,CHECK-DARWIN %s
+
+// non trivially copyable, forces inalloca
+struct S {
+ S(const S &s) {}
+};
+
+@interface C
+@end
+
+@implementation C
+- (void)object:(id)obj struct:(S)s {
+}
+@end
+
+// CHECK-GNUSTEP: define internal void @_i_C__object_struct_(<{ %0*, i8*, i8*, %struct.S, [3 x i8] }>* inalloca)
+// CHECK-DARWIN: define internal void @"\01-[C object:struct:]"(<{ %0*, i8*, i8*, %struct.S, [3 x i8] }>* inalloca)
+// CHECK: %obj = getelementptr inbounds <{ %0*, i8*, i8*, %struct.S, [3 x i8] }>, <{ %0*, i8*, i8*, %struct.S, [3 x i8] }>* %0, i32 0, i32 2
+// CHECK: %[[INSTANCE:[0-9]+]] = load i8*, i8** %obj, align 4
+// CHECK: call void @objc_storeStrong(i8** %obj, i8* %[[INSTANCE]])
diff --git a/test/CodeGenOpenCL/addr-space-struct-arg.cl b/test/CodeGenOpenCL/addr-space-struct-arg.cl
index d711f78d4ef0..6ea0aff0a074 100644
--- a/test/CodeGenOpenCL/addr-space-struct-arg.cl
+++ b/test/CodeGenOpenCL/addr-space-struct-arg.cl
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 %s -emit-llvm -o - -O0 -ffake-address-space-map -triple i686-pc-darwin | FileCheck %s
+// RUN: %clang_cc1 %s -emit-llvm -o - -O0 -finclude-default-header -ffake-address-space-map -triple i686-pc-darwin | FileCheck -check-prefixes=COM,X86 %s
+// RUN: %clang_cc1 %s -emit-llvm -o - -O0 -finclude-default-header -triple amdgcn-amdhsa-amd-amdgizcl | FileCheck -check-prefixes=COM,AMD %s
typedef struct {
int cells[9];
@@ -8,16 +9,57 @@ typedef struct {
int cells[16];
} Mat4X4;
+struct StructOneMember {
+ int2 x;
+};
+
+struct StructTwoMember {
+ int2 x;
+ int2 y;
+};
+
+// COM-LABEL: define void @foo
Mat4X4 __attribute__((noinline)) foo(Mat3X3 in) {
Mat4X4 out;
return out;
}
+// COM-LABEL: define {{.*}} void @ker
+// Expect two mem copies: one for the argument "in", and one for
+// the return value.
+// X86: call void @llvm.memcpy.p0i8.p1i8.i32(i8*
+// X86: call void @llvm.memcpy.p1i8.p0i8.i32(i8 addrspace(1)*
+// AMD: call void @llvm.memcpy.p5i8.p1i8.i64(i8 addrspace(5)*
+// AMD: call void @llvm.memcpy.p1i8.p5i8.i64(i8 addrspace(1)*
kernel void ker(global Mat3X3 *in, global Mat4X4 *out) {
out[0] = foo(in[1]);
}
-// Expect two mem copies: one for the argument "in", and one for
-// the return value.
-// CHECK: call void @llvm.memcpy.p0i8.p1i8.i32(i8*
-// CHECK: call void @llvm.memcpy.p1i8.p0i8.i32(i8 addrspace(1)*
+// AMD-LABEL: define void @FuncOneMember(%struct.StructOneMember addrspace(5)* byval align 8 %u)
+void FuncOneMember(struct StructOneMember u) {
+ u.x = (int2)(0, 0);
+}
+
+// AMD-LABEL: define amdgpu_kernel void @KernelOneMember
+// AMD-SAME: (<2 x i32> %[[u_coerce:.*]])
+// AMD: %[[u:.*]] = alloca %struct.StructOneMember, align 8, addrspace(5)
+// AMD: %[[coerce_dive:.*]] = getelementptr inbounds %struct.StructOneMember, %struct.StructOneMember addrspace(5)* %[[u]], i32 0, i32 0
+// AMD: store <2 x i32> %[[u_coerce]], <2 x i32> addrspace(5)* %[[coerce_dive]]
+// AMD: call void @FuncOneMember(%struct.StructOneMember addrspace(5)* byval align 8 %[[u]])
+kernel void KernelOneMember(struct StructOneMember u) {
+ FuncOneMember(u);
+}
+
+// AMD-LABEL: define void @FuncTwoMember(%struct.StructTwoMember addrspace(5)* byval align 8 %u)
+void FuncTwoMember(struct StructTwoMember u) {
+ u.x = (int2)(0, 0);
+}
+
+// AMD-LABEL: define amdgpu_kernel void @KernelTwoMember
+// AMD-SAME: (%struct.StructTwoMember %[[u_coerce:.*]])
+// AMD: %[[u:.*]] = alloca %struct.StructTwoMember, align 8, addrspace(5)
+// AMD: store %struct.StructTwoMember %[[u_coerce]], %struct.StructTwoMember addrspace(5)* %[[u]]
+// AMD: call void @FuncTwoMember(%struct.StructTwoMember addrspace(5)* byval align 8 %[[u]])
+kernel void KernelTwoMember(struct StructTwoMember u) {
+ FuncTwoMember(u);
+}
diff --git a/test/Driver/arm-execute-only.c b/test/Driver/arm-execute-only.c
index a4854485e1e4..c226a7f3b4b1 100644
--- a/test/Driver/arm-execute-only.c
+++ b/test/Driver/arm-execute-only.c
@@ -1,39 +1,3 @@
-// RUN: %clang -target armv6t2-eabi -### %s 2>&1 \
-// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
-
-// RUN: %clang -target armv6t2-eabi -### -mexecute-only %s 2>&1 \
-// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY
-
-// RUN: %clang -target armv6t2-eabi -### -mexecute-only -mno-execute-only %s 2>&1 \
-// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
-
-// RUN: %clang -target armv7m-eabi -### %s 2>&1 \
-// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
-
-// RUN: %clang -target armv7m-eabi -### -mexecute-only %s 2>&1 \
-// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY
-
-// RUN: %clang -target armv7m-eabi -### -mexecute-only -mno-execute-only %s 2>&1 \
-// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
-
-// RUN: %clang -target armv8m.base-eabi -### %s 2>&1 \
-// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
-
-// RUN: %clang -target armv8m.base-eabi -### -mexecute-only %s 2>&1 \
-// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY
-
-// RUN: %clang -target armv8m.base-eabi -### -mexecute-only -mno-execute-only %s 2>&1 \
-// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
-
-// RUN: %clang -target armv8m.main-eabi -### %s 2>&1 \
-// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
-
-// RUN: %clang -target armv8m.main-eabi -### -mexecute-only %s 2>&1 \
-// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY
-
-// RUN: %clang -target armv8m.main-eabi -### -mexecute-only -mno-execute-only %s 2>&1 \
-// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
-
// RUN: not %clang -c -target thumbv6m-eabi -mexecute-only %s 2>&1 | \
// RUN: FileCheck --check-prefix CHECK-EXECUTE-ONLY-NOT-SUPPORTED %s
@@ -45,42 +9,6 @@
// -mpure-code flag for GCC compatibility
-// RUN: %clang -target armv6t2-eabi -### %s 2>&1 \
-// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
-
-// RUN: %clang -target armv6t2-eabi -### -mpure-code %s 2>&1 \
-// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY
-
-// RUN: %clang -target armv6t2-eabi -### -mpure-code -mno-pure-code %s 2>&1 \
-// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
-
-// RUN: %clang -target armv7m-eabi -### %s 2>&1 \
-// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
-
-// RUN: %clang -target armv7m-eabi -### -mpure-code %s 2>&1 \
-// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY
-
-// RUN: %clang -target armv7m-eabi -### -mpure-code -mno-pure-code %s 2>&1 \
-// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
-
-// RUN: %clang -target armv8m.base-eabi -### %s 2>&1 \
-// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
-
-// RUN: %clang -target armv8m.base-eabi -### -mpure-code %s 2>&1 \
-// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY
-
-// RUN: %clang -target armv8m.base-eabi -### -mpure-code -mno-pure-code %s 2>&1 \
-// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
-
-// RUN: %clang -target armv8m.main-eabi -### %s 2>&1 \
-// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
-
-// RUN: %clang -target armv8m.main-eabi -### -mpure-code %s 2>&1 \
-// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY
-
-// RUN: %clang -target armv8m.main-eabi -### -mpure-code -mno-pure-code %s 2>&1 \
-// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
-
// RUN: not %clang -c -target thumbv6m-eabi -mpure-code %s 2>&1 | \
// RUN: FileCheck --check-prefix CHECK-EXECUTE-ONLY-NOT-SUPPORTED %s
diff --git a/test/Driver/clang_f_opts.c b/test/Driver/clang_f_opts.c
index bad49942a4c4..e4b72d69ca3f 100644
--- a/test/Driver/clang_f_opts.c
+++ b/test/Driver/clang_f_opts.c
@@ -178,13 +178,6 @@
// CHECK-SLP-VECTORIZE: "-vectorize-slp"
// CHECK-NO-SLP-VECTORIZE-NOT: "-vectorize-slp"
-// RUN: %clang -### -S -fslp-vectorize-aggressive %s 2>&1 | FileCheck -check-prefix=CHECK-SLP-VECTORIZE-AGG %s
-// RUN: %clang -### -S -fno-slp-vectorize-aggressive -fslp-vectorize-aggressive %s 2>&1 | FileCheck -check-prefix=CHECK-SLP-VECTORIZE-AGG %s
-// RUN: %clang -### -S -fno-slp-vectorize-aggressive %s 2>&1 | FileCheck -check-prefix=CHECK-NO-SLP-VECTORIZE-AGG %s
-// RUN: %clang -### -S -fslp-vectorize-aggressive -fno-slp-vectorize-aggressive %s 2>&1 | FileCheck -check-prefix=CHECK-NO-SLP-VECTORIZE-AGG %s
-// CHECK-SLP-VECTORIZE-AGG: "-vectorize-slp-aggressive"
-// CHECK-NO-SLP-VECTORIZE-AGG-NOT: "-vectorize-slp-aggressive"
-
// RUN: %clang -### -S -fextended-identifiers %s 2>&1 | FileCheck -check-prefix=CHECK-EXTENDED-IDENTIFIERS %s
// RUN: not %clang -### -S -fno-extended-identifiers %s 2>&1 | FileCheck -check-prefix=CHECK-NO-EXTENDED-IDENTIFIERS %s
// CHECK-EXTENDED-IDENTIFIERS: "-cc1"
diff --git a/test/Driver/darwin-version.c b/test/Driver/darwin-version.c
index 8f08bb9dec4a..c11a2df37f98 100644
--- a/test/Driver/darwin-version.c
+++ b/test/Driver/darwin-version.c
@@ -10,6 +10,41 @@
// RUN: %clang -target armv6-apple-darwin9 -miphoneos-version-min=3.0 -c %s -### 2>&1 | \
// RUN: FileCheck --check-prefix=CHECK-VERSION-IOS3 %s
// CHECK-VERSION-IOS3: "armv6k-apple-ios3.0.0"
+
+// RUN: env IPHONEOS_DEPLOYMENT_TARGET=11.0 \
+// RUN: %clang -target armv7-apple-ios9.0 -c -### %s 2> %t.err
+// RUN: FileCheck --input-file=%t.err --check-prefix=CHECK-VERSION-IOS4 %s
+// CHECK-VERSION-IOS4: invalid iOS deployment version 'IPHONEOS_DEPLOYMENT_TARGET=11.0'
+
+// RUN: %clang -target armv7-apple-ios9.0 -miphoneos-version-min=11.0 -c -### %s 2> %t.err
+// RUN: FileCheck --input-file=%t.err --check-prefix=CHECK-VERSION-IOS5 %s
+// CHECK-VERSION-IOS5: invalid iOS deployment version '-miphoneos-version-min=11.0'
+
+// RUN: %clang -target i386-apple-darwin -mios-simulator-version-min=11.0 -c -### %s 2> %t.err
+// RUN: FileCheck --input-file=%t.err --check-prefix=CHECK-VERSION-IOS6 %s
+// CHECK-VERSION-IOS6: invalid iOS deployment version '-mios-simulator-version-min=11.0'
+
+// RUN: %clang -target armv7-apple-ios11.1 -c -### %s 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-VERSION-IOS7 %s
+// CHECK-VERSION-IOS7: thumbv7-apple-ios10.99.99
+
+// RUN: env IPHONEOS_DEPLOYMENT_TARGET=11.0 \
+// RUN: %clang -target arm64-apple-ios11.0 -c -### %s 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-VERSION-IOS8 %s
+// CHECK-VERSION-IOS8: arm64-apple-ios11.0.0
+
+// RUN: %clang -target arm64-apple-ios11.0 -miphoneos-version-min=11.0 -c -### %s 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-VERSION-IOS9 %s
+// CHECK-VERSION-IOS9: arm64-apple-ios11.0.0
+
+// RUN: %clang -target x86_64-apple-darwin -mios-simulator-version-min=11.0 -c -### %s 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-VERSION-IOS10 %s
+// CHECK-VERSION-IOS10: x86_64-apple-ios11.0.0
+
+// RUN: %clang -target arm64-apple-ios11.1 -c -### %s 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-VERSION-IOS11 %s
+// CHECK-VERSION-IOS11: arm64-apple-ios11.1.0
+
// RUN: %clang -target i686-apple-darwin8 -c %s -### 2>&1 | \
// RUN: FileCheck --check-prefix=CHECK-VERSION-OSX4 %s
// RUN: %clang -target i686-apple-darwin9 -mmacosx-version-min=10.4 -c %s -### 2>&1 | \
diff --git a/test/Driver/fuzzer.c b/test/Driver/fuzzer.c
index e534a73a647f..989b3b9f6348 100644
--- a/test/Driver/fuzzer.c
+++ b/test/Driver/fuzzer.c
@@ -15,6 +15,14 @@
//
// CHECK-LIBCXX-DARWIN: -lc++
+
+// Check that we don't link in libFuzzer.a when producing a shared object.
+// RUN: %clang -fsanitize=fuzzer %s -shared -o %t.so -### 2>&1 | FileCheck --check-prefixes=CHECK-NOLIB-SO %s
+// CHECK-NOLIB-SO-NOT: libLLVMFuzzer.a
+
+// RUN: %clang -fsanitize=fuzzer -fsanitize-coverage=trace-pc %s -### 2>&1 | FileCheck --check-prefixes=CHECK-MSG %s
+// CHECK-MSG-NOT: argument unused during compilation
+
int LLVMFuzzerTestOneInput(const char *Data, long Size) {
return 0;
}
diff --git a/test/Driver/nios2-cpu.c b/test/Driver/nios2-cpu.c
new file mode 100644
index 000000000000..d98f0384a66d
--- /dev/null
+++ b/test/Driver/nios2-cpu.c
@@ -0,0 +1,26 @@
+// RUN: %clang -target nios2--- %s -### -o %t.o 2>&1 \
+// RUN: | FileCheck %s
+
+// RUN: %clang -target nios2--- -mcpu=r1 %s -### -o %t.o 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-R1 %s
+// RUN: %clang -target nios2--- -mcpu=nios2r1 %s -### -o %t.o 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-R1 %s
+// RUN: %clang -target nios2--- -march=r1 %s -### -o %t.o 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-R1 %s
+// RUN: %clang -target nios2--- -march=nios2r1 %s -### -o %t.o 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-R1 %s
+
+// RUN: %clang -target nios2--- -mcpu=r2 %s -### -o %t.o 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-R2 %s
+// RUN: %clang -target nios2--- -mcpu=nios2r2 %s -### -o %t.o 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-R2 %s
+// RUN: %clang -target nios2--- -march=r2 %s -### -o %t.o 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-R2 %s
+// RUN: %clang -target nios2--- -march=nios2r2 %s -### -o %t.o 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-R2 %s
+
+// CHECK: "-triple" "nios2---"
+// CHECK-R1: "-triple" "nios2---"
+// CHECK-R1: "-target-cpu" "nios2r1"
+// CHECK-R2: "-triple" "nios2---"
+// CHECK-R2: "-target-cpu" "nios2r2"
diff --git a/test/Driver/openmp-offload.c b/test/Driver/openmp-offload.c
index 39eb41e6ac08..d43aa331c9dc 100644
--- a/test/Driver/openmp-offload.c
+++ b/test/Driver/openmp-offload.c
@@ -250,15 +250,15 @@
//
// Compile for the powerpc device.
//
-// CHK-COMMANDS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-emit-obj" {{.*}}"-pic-level" "2" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-COMMANDS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-obj" {{.*}}"-pic-level" "2" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-COMMANDS-SAME: [[T1OBJ:[^\\/]+\.o]]" "-x" "c" "{{.*}}[[INPUT]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
// CHK-COMMANDS: ld{{(\.exe)?}}" {{.*}}"-o" "
// CHK-COMMANDS-SAME: [[T1BIN:[^\\/]+\.out]]" {{.*}}"{{.*}}[[T1OBJ]]"
-// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-E" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le--linux" "-E" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-COMMANDS-ST-SAME: [[T1PP:[^\\/]+\.i]]" "-x" "c" "{{.*}}[[INPUT]]"
-// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-emit-llvm-bc" {{.*}}"-pic-level" "2" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-llvm-bc" {{.*}}"-pic-level" "2" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-COMMANDS-ST-SAME: [[T1BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T1PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
-// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le--linux" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-COMMANDS-ST-SAME: [[T1ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T1BC]]"
// CHK-COMMANDS-ST: clang{{.*}}" "-cc1as" "-triple" "powerpc64le-ibm-linux-gnu" "-filetype" "obj" {{.*}}"-o" "
// CHK-COMMANDS-ST-SAME: [[T1OBJ:[^\\/]+\.o]]" "{{.*}}[[T1ASM]]"
@@ -267,15 +267,15 @@
//
// Compile for the x86 device.
//
-// CHK-COMMANDS: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-emit-obj" {{.*}}"-pic-level" "2" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-COMMANDS: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-obj" {{.*}}"-pic-level" "2" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-COMMANDS-SAME: [[T2OBJ:[^\\/]+\.o]]" "-x" "c" "{{.*}}[[INPUT]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
// CHK-COMMANDS: ld{{(\.exe)?}}" {{.*}}"-o" "
// CHK-COMMANDS-SAME: [[T2BIN:[^\\/]+\.out]]" {{.*}}"{{.*}}[[T2OBJ]]"
-// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-E" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le--linux" "-E" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-COMMANDS-ST-SAME: [[T2PP:[^\\/]+\.i]]" "-x" "c" "{{.*}}[[INPUT]]"
-// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-emit-llvm-bc" {{.*}}"-pic-level" "2" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-llvm-bc" {{.*}}"-pic-level" "2" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-COMMANDS-ST-SAME: [[T2BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T2PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
-// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le--linux" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-COMMANDS-ST-SAME: [[T2ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T2BC]]"
// CHK-COMMANDS-ST: clang{{.*}}" "-cc1as" "-triple" "x86_64-pc-linux-gnu" "-filetype" "obj" {{.*}}"-o" "
// CHK-COMMANDS-ST-SAME: [[T2OBJ:[^\\/]+\.o]]" "{{.*}}[[T2ASM]]"
@@ -398,25 +398,25 @@
// CHK-BUJOBS-ST-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[HOSTPP]]" "-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu"
// Create target 1 object.
-// CHK-BUJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-BUJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-BUJOBS-SAME: [[T1OBJ:[^\\/]+\.o]]" "-x" "c" "{{.*}}[[INPUT]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
-// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-E" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le--linux" "-E" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-BUJOBS-ST-SAME: [[T1PP:[^\\/]+\.i]]" "-x" "c" "{{.*}}[[INPUT]]"
-// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-BUJOBS-ST-SAME: [[T1BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T1PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
-// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le--linux" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-BUJOBS-ST-SAME: [[T1ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T1BC]]"
// CHK-BUJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "powerpc64le-ibm-linux-gnu" "-filetype" "obj" {{.*}}"-o" "
// CHK-BUJOBS-ST-SAME: [[T1OBJ:[^\\/]+\.o]]" "{{.*}}[[T1ASM]]"
// Create target 2 object.
-// CHK-BUJOBS: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-BUJOBS: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-BUJOBS-SAME: [[T2OBJ:[^\\/]+\.o]]" "-x" "c" "{{.*}}[[INPUT]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
-// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-E" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le--linux" "-E" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-BUJOBS-ST-SAME: [[T2PP:[^\\/]+\.i]]" "-x" "c" "{{.*}}[[INPUT]]"
-// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-BUJOBS-ST-SAME: [[T2BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T2PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
-// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le--linux" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-BUJOBS-ST-SAME: [[T2ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T2BC]]"
// CHK-BUJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "x86_64-pc-linux-gnu" "-filetype" "obj" {{.*}}"-o" "
// CHK-BUJOBS-ST-SAME: [[T2OBJ:[^\\/]+\.o]]" "{{.*}}[[T2ASM]]"
@@ -464,13 +464,13 @@
// CHK-UBJOBS-ST-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[HOSTPP]]" "-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu"
// Create target 1 object.
-// CHK-UBJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-UBJOBS-SAME: [[T1OBJ:[^\\/]+\.o]]" "-x" "cpp-output" "{{.*}}[[T1PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
// CHK-UBJOBS: ld{{(\.exe)?}}" {{.*}}"-o" "
// CHK-UBJOBS-SAME: [[T1BIN:[^\\/]+\.out]]" {{.*}}"{{.*}}[[T1OBJ]]"
-// CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-UBJOBS-ST-SAME: [[T1BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T1PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
-// CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le--linux" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-UBJOBS-ST-SAME: [[T1ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T1BC]]"
// CHK-UBJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "powerpc64le-ibm-linux-gnu" "-filetype" "obj" {{.*}}"-o" "
// CHK-UBJOBS-ST-SAME: [[T1OBJ:[^\\/]+\.o]]" "{{.*}}[[T1ASM]]"
@@ -478,13 +478,13 @@
// CHK-UBJOBS-ST-SAME: [[T1BIN:[^\\/]+\.out-openmp-powerpc64le-ibm-linux-gnu]]" {{.*}}"{{.*}}[[T1OBJ]]"
// Create target 2 object.
-// CHK-UBJOBS: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBJOBS: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-UBJOBS-SAME: [[T2OBJ:[^\\/]+\.o]]" "-x" "cpp-output" "{{.*}}[[T2PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
// CHK-UBJOBS: ld{{(\.exe)?}}" {{.*}}"-o" "
// CHK-UBJOBS-SAME: [[T2BIN:[^\\/]+\.out]]" {{.*}}"{{.*}}[[T2OBJ]]"
-// CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-UBJOBS-ST-SAME: [[T2BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T2PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
-// CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le--linux" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-UBJOBS-ST-SAME: [[T2ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T2BC]]"
// CHK-UBJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "x86_64-pc-linux-gnu" "-filetype" "obj" {{.*}}"-o" "
// CHK-UBJOBS-ST-SAME: [[T2OBJ:[^\\/]+\.o]]" "{{.*}}[[T2ASM]]"
@@ -559,21 +559,21 @@
// CHK-UBUJOBS-ST-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[HOSTPP]]" "-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu"
// Create target 1 object.
-// CHK-UBUJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBUJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-UBUJOBS-SAME: [[T1OBJ:[^\\/]+\.o]]" "-x" "cpp-output" "{{.*}}[[T1PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
-// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-UBUJOBS-ST-SAME: [[T1BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T1PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
-// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le--linux" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-UBUJOBS-ST-SAME: [[T1ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T1BC]]"
// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "powerpc64le-ibm-linux-gnu" "-filetype" "obj" {{.*}}"-o" "
// CHK-UBUJOBS-ST-SAME: [[T1OBJ:[^\\/]+\.o]]" "{{.*}}[[T1ASM]]"
// Create target 2 object.
-// CHK-UBUJOBS: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBUJOBS: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-UBUJOBS-SAME: [[T2OBJ:[^\\/]+\.o]]" "-x" "cpp-output" "{{.*}}[[T2PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
-// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-UBUJOBS-ST-SAME: [[T2BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T2PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
-// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le--linux" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-UBUJOBS-ST-SAME: [[T2ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T2BC]]"
// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "x86_64-pc-linux-gnu" "-filetype" "obj" {{.*}}"-o" "
// CHK-UBUJOBS-ST-SAME: [[T2OBJ:[^\\/]+\.o]]" "{{.*}}[[T2ASM]]"
@@ -589,3 +589,11 @@
// CHK-UBUJOBS-ST-SAME: [[HOSTOBJ:[^\\/]+\.o]]" "{{.*}}[[HOSTASM]]"
// CHK-UBUJOBS-ST: clang-offload-bundler{{.*}}" "-type=o" "-targets=openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu,host-powerpc64le--linux" "-outputs=
// CHK-UBUJOBS-ST-SAME: [[RES:[^\\/]+\.o]]" "-inputs={{.*}}[[T1OBJ]],{{.*}}[[T2OBJ]],{{.*}}[[HOSTOBJ]]"
+
+/// ###########################################################################
+
+/// Check -fopenmp-is-device is passed when compiling for the device.
+// RUN: %clang -### -no-canonical-prefixes -target powerpc64le-linux -fopenmp=libomp -fopenmp-targets=powerpc64le-ibm-linux-gnu %s 2>&1 \
+// RUN: | FileCheck -check-prefix=CHK-FOPENMP-IS-DEVICE %s
+
+// CHK-FOPENMP-IS-DEVICE: clang{{.*}} "-aux-triple" "powerpc64le--linux" {{.*}}.c" "-fopenmp-is-device" "-fopenmp-host-ir-file-path"
diff --git a/test/Driver/unavailable_aligned_allocation.cpp b/test/Driver/unavailable_aligned_allocation.cpp
new file mode 100644
index 000000000000..cd75c08165d7
--- /dev/null
+++ b/test/Driver/unavailable_aligned_allocation.cpp
@@ -0,0 +1,54 @@
+// RUN: %clang -target x86_64-apple-macosx10.12 -c -### %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix=UNAVAILABLE
+//
+// RUN: %clang -target arm64-apple-ios10 -c -### %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix=UNAVAILABLE
+//
+// RUN: %clang -target arm64-apple-tvos10 -c -### %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix=UNAVAILABLE
+//
+// RUN: %clang -target thumbv7-apple-watchos3 -c -### %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix=UNAVAILABLE
+//
+// RUN: %clang -target x86_64-apple-macosx10.13 -mios-simulator-version-min=10 \
+// RUN: -c -### %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix=UNAVAILABLE
+//
+// RUN: %clang -target x86_64-apple-macosx10.13 -mtvos-simulator-version-min=10 \
+// RUN: -c -### %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix=UNAVAILABLE
+//
+// RUN: %clang -target x86_64-apple-macosx10.13 -mwatchos-simulator-version-min=3 \
+// RUN: -c -### %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix=UNAVAILABLE
+//
+// UNAVAILABLE: "-faligned-alloc-unavailable"
+
+// RUN: %clang -target x86_64-apple-macosx10.13 -c -### %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix=AVAILABLE
+//
+// RUN: %clang -target arm64-apple-ios11 -c -### %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix=AVAILABLE
+//
+// RUN: %clang -target arm64-apple-tvos11 -c -### %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix=AVAILABLE
+//
+// RUN: %clang -target armv7k-apple-watchos4 -c -### %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix=AVAILABLE
+//
+// RUN: %clang -target x86_64-unknown-linux-gnu -c -### %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix=AVAILABLE
+//
+// RUN: %clang -target x86_64-apple-macosx10.12 -mios-simulator-version-min=11 \
+// RUN: -c -### %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix=AVAILABLE
+//
+// RUN: %clang -target x86_64-apple-macosx10.12 -mtvos-simulator-version-min=11 \
+// RUN: -c -### %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix=AVAILABLE
+//
+// RUN: %clang -target x86_64-apple-macosx10.12 -mwatchos-simulator-version-min=4 \
+// RUN: -c -### %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix=AVAILABLE
+//
+// AVAILABLE-NOT: "-faligned-alloc-unavailable"
diff --git a/test/Driver/windows-cross.c b/test/Driver/windows-cross.c
index 90fefbadfea1..0e688f0a26e7 100644
--- a/test/Driver/windows-cross.c
+++ b/test/Driver/windows-cross.c
@@ -80,3 +80,8 @@
// CHECK-ISYSTEM-AFTER: "-internal-isystem" "Windows Kits{{[/\\]}}10{{[/\\]}}Include{{[/\\]}}10.0.10586.0{{[/\\]}}um"
// CHECK-ISYSTEM-AFTER: "-internal-isystem" "Windows Kits{{[/\\]}}10{{[/\\]}}Include{{[/\\]}}10.0.10586.0{{[/\\]}}shared"
+// RUN: %clang -### -target armv7-windows-itanium -nostdinc -isystem-after "Windows Kits/10/Include/10.0.10586.0/ucrt" -c %s -o /dev/null 2>&1 \
+// RUN: | FileCheck %s --check-prefix CHECK-NOSTDINC-ISYSTEM-AFTER
+// CHECK-NOSTDINC-ISYSTEM-AFTER: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]"
+// CHECK-NOSTDINC-ISYSTEM-AFTER-NOT: "-internal-isystem" "[[RESOURCE_DIR]]{{(/|\\\\)}}include"
+// CHECK-NOSTDINC-ISYSTEM-AFTER: "-internal-isystem" "Windows Kits{{[/\\]}}10{{[/\\]}}Include{{[/\\]}}10.0.10586.0{{[/\\]}}ucrt"
diff --git a/test/FixIt/fixit-format-darwin.m b/test/FixIt/fixit-format-darwin.m
index 077cc0cf21bc..54d25d92c2b3 100644
--- a/test/FixIt/fixit-format-darwin.m
+++ b/test/FixIt/fixit-format-darwin.m
@@ -8,12 +8,15 @@
int printf(const char * restrict, ...);
#if __LP64__
+typedef long CFIndex;
typedef long NSInteger;
typedef unsigned long NSUInteger;
#else
+typedef int CFIndex;
typedef int NSInteger;
typedef unsigned int NSUInteger;
#endif
+CFIndex getCFIndex();
NSInteger getNSInteger();
NSUInteger getNSUInteger();
@@ -74,3 +77,10 @@ void bug33447() {
Outer2("test 9: %s %s", getNSInteger(), getNSInteger());
// CHECK: Outer2("test 9: %ld %ld", (long)getNSInteger(), (long)getNSInteger());
}
+
+void testCFIndex() {
+ printf("test 10: %s", getCFIndex());
+ // CHECK: printf("test 10: %ld", (long)getCFIndex());
+ printf("test 11: %s %s", getCFIndex(), getCFIndex());
+ // CHECK: printf("test 11: %ld %ld", (long)getCFIndex(), (long)getCFIndex());
+}
diff --git a/test/FixIt/format-darwin.m b/test/FixIt/format-darwin.m
index 170bb09fb904..fcc81036fcf3 100644
--- a/test/FixIt/format-darwin.m
+++ b/test/FixIt/format-darwin.m
@@ -7,13 +7,14 @@
int printf(const char * restrict, ...);
#if __LP64__
+typedef long CFIndex;
typedef long NSInteger;
typedef unsigned long NSUInteger;
typedef int SInt32;
typedef unsigned int UInt32;
#else
-
+typedef int CFIndex;
typedef int NSInteger;
typedef unsigned int NSUInteger;
typedef long SInt32;
@@ -27,6 +28,7 @@ typedef enum NSIntegerEnum : NSInteger {
EnumValueB
} NSIntegerEnum;
+CFIndex getCFIndex();
NSInteger getNSInteger();
NSUInteger getNSUInteger();
SInt32 getSInt32();
@@ -55,6 +57,11 @@ void testCorrectionInAllCases() {
// CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:11-[[@LINE-2]]:13}:"%ld"
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:16-[[@LINE-3]]:16}:"(long)"
+
+ printf("%s", getCFIndex()); // expected-warning{{values of type 'CFIndex' should not be used as format arguments; add an explicit cast to 'long' instead}}
+
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:11-[[@LINE-2]]:13}:"%ld"
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:16-[[@LINE-3]]:16}:"(long)"
}
@interface Foo {
@@ -120,6 +127,11 @@ void testWarn() {
// CHECK-64: fix-it:"{{.*}}":{[[@LINE-2]]:11-[[@LINE-2]]:13}:"%ld"
// CHECK-64: fix-it:"{{.*}}":{[[@LINE-3]]:16-[[@LINE-3]]:16}:"(long)"
+
+ printf("%d", getCFIndex()); // expected-warning{{values of type 'CFIndex' should not be used as format arguments; add an explicit cast to 'long' instead}}
+
+ // CHECK-64: fix-it:"{{.*}}":{[[@LINE-2]]:11-[[@LINE-2]]:13}:"%ld"
+ // CHECK-64: fix-it:"{{.*}}":{[[@LINE-3]]:16-[[@LINE-3]]:16}:"(long)"
}
void testPreserveHex() {
@@ -167,6 +179,10 @@ void testWarn() {
printf("%ld", getNSIntegerEnum()); // expected-warning{{enum values with underlying type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead}}
// CHECK-32: fix-it:"{{.*}}":{[[@LINE-2]]:17-[[@LINE-2]]:17}:"(long)"
+
+ printf("%ld", getCFIndex()); // expected-warning{{values of type 'CFIndex' should not be used as format arguments; add an explicit cast to 'long' instead}}
+
+ // CHECK-32: fix-it:"{{.*}}":{[[@LINE-2]]:17-[[@LINE-2]]:17}:"(long)"
}
void testPreserveHex() {
@@ -218,6 +234,11 @@ void testCasts() {
// CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:11-[[@LINE-2]]:13}:"%ld"
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:16-[[@LINE-3]]:31}:"(long)"
+
+ printf("%s", (CFIndex)0); // expected-warning{{values of type 'CFIndex' should not be used as format arguments; add an explicit cast to 'long' instead}}
+
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:11-[[@LINE-2]]:13}:"%ld"
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:16-[[@LINE-3]]:25}:"(long)"
}
void testCapitals() {
diff --git a/test/Frontend/Inputs/optimization-remark-with-hotness-sample.proftext b/test/Frontend/Inputs/optimization-remark-with-hotness-sample.proftext
index aeea583de4d4..730dc4a0d5b1 100644
--- a/test/Frontend/Inputs/optimization-remark-with-hotness-sample.proftext
+++ b/test/Frontend/Inputs/optimization-remark-with-hotness-sample.proftext
@@ -1,7 +1,7 @@
foo:0:0
0: 0
bar:29:29
- 6: foo:0
+ 9: foo:0
main:0:0
0: 0 bar:0
diff --git a/test/Frontend/optimization-remark-with-hotness.c b/test/Frontend/optimization-remark-with-hotness.c
index 30ead64b8eb5..875fc75ae159 100644
--- a/test/Frontend/optimization-remark-with-hotness.c
+++ b/test/Frontend/optimization-remark-with-hotness.c
@@ -15,12 +15,14 @@
// RUN: optimization-remark-with-hotness.c %s -emit-llvm-only \
// RUN: -fprofile-sample-use=%t-sample.profdata -Rpass=inline \
// RUN: -Rpass-analysis=inline -Rpass-missed=inline \
-// RUN: -fdiagnostics-show-hotness -verify
+// RUN: -fdiagnostics-show-hotness -fdiagnostics-hotness-threshold=10 \
+// RUN: -verify
// The clang version of the previous test.
// RUN: %clang -target x86_64-apple-macosx10.9 %s -c -emit-llvm -o /dev/null \
// RUN: -fprofile-instr-use=%t.profdata -Rpass=inline \
// RUN: -Rpass-analysis=inline -Rpass-missed=inline \
-// RUN: -fdiagnostics-show-hotness -Xclang -verify
+// RUN: -fdiagnostics-show-hotness -fdiagnostics-hotness-threshold=10 \
+// RUN: -Xclang -verify
// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name \
// RUN: optimization-remark-with-hotness.c %s -emit-llvm-only \
// RUN: -fprofile-instrument-use-path=%t.profdata -Rpass=inline \
@@ -28,11 +30,18 @@
// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name \
// RUN: optimization-remark-with-hotness.c %s -emit-llvm-only \
// RUN: -fprofile-instrument-use-path=%t.profdata -Rpass=inline \
-// RUN: -Rpass-analysis=inline -Rno-pass-with-hotness 2>&1 | FileCheck \
+// RUN: -Rpass-analysis=inline -Rno-pass-with-hotness 2>&1 | FileCheck \
// RUN: -check-prefix=HOTNESS_OFF %s
// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name \
// RUN: optimization-remark-with-hotness.c %s -emit-llvm-only \
-// RUN: -Rpass=inline -Rpass-analysis=inline -fdiagnostics-show-hotness 2>&1 \
+// RUN: -fprofile-instrument-use-path=%t.profdata -Rpass=inline \
+// RUN: -Rpass-analysis=inline -fdiagnostics-show-hotness \
+// RUN: -fdiagnostics-hotness-threshold=100 2>&1 \
+// RUN: | FileCheck -allow-empty -check-prefix=THRESHOLD %s
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name \
+// RUN: optimization-remark-with-hotness.c %s -emit-llvm-only \
+// RUN: -Rpass=inline -Rpass-analysis=inline \
+// RUN: -fdiagnostics-show-hotness -fdiagnostics-hotness-threshold=10 2>&1 \
// RUN: | FileCheck -check-prefix=NO_PGO %s
int foo(int x, int y) __attribute__((always_inline));
@@ -43,7 +52,10 @@ int sum = 0;
void bar(int x) {
// HOTNESS_OFF: foo inlined into bar
// HOTNESS_OFF-NOT: hotness:
+ // THRESHOLD-NOT: inlined
+ // THRESHOLD-NOT: hotness
// NO_PGO: '-fdiagnostics-show-hotness' requires profile-guided optimization information
+ // NO_PGO: '-fdiagnostics-hotness-threshold=' requires profile-guided optimization information
// expected-remark@+2 {{foo should always be inlined (cost=always) (hotness: 30)}}
// expected-remark@+1 {{foo inlined into bar (hotness: 30)}}
sum += foo(x, x - 2);
diff --git a/test/Index/ctor-init-source-loc.cpp b/test/Index/ctor-init-source-loc.cpp
new file mode 100644
index 000000000000..ff93e58092da
--- /dev/null
+++ b/test/Index/ctor-init-source-loc.cpp
@@ -0,0 +1,117 @@
+// RUN: c-index-test -test-load-source all %s -fno-delayed-template-parsing | FileCheck %s
+template<typename MyBase>
+struct Derived: MyBase::InnerIterator
+{
+ Derived() : MyBase::InnerIterator() {}
+// CHECK: TypeRef=MyBase:2:19 Extent=[5:17 - 5:23]
+};
+
+template<typename MyBase>
+struct Derived2: MyBase::Deeper::InnerIterator
+{
+ Derived2() : MyBase::Deeper::InnerIterator() {}
+// CHECK: TypeRef=MyBase:9:19 Extent=[12:18 - 12:24]
+};
+
+template<typename Q>
+struct Templ;
+
+template<typename MyBase>
+struct Derived3: Templ<MyBase>::InnerIterator
+{
+ Derived3() : Templ<MyBase>::InnerIterator() {}
+// CHECK: TemplateRef=Templ:17:8 Extent=[22:18 - 22:23]
+// CHECK: TypeRef=MyBase:19:19 Extent=[22:24 - 22:30]
+};
+
+
+struct Outer {
+ template <typename Q>
+ struct Inner {
+ typedef Q Parm;
+ };
+};
+
+template<typename Q>
+struct Derived4: Outer::Inner<Q>::Parm
+{
+ Derived4() : Outer::Inner<Q>::Parm() {}
+// CHECK: TypeRef=struct Outer:28:8 Extent=[38:18 - 38:23]
+// CHECK: TemplateRef=Inner:30:12 Extent=[38:25 - 38:30]
+// CHECK: TypeRef=Q:35:19 Extent=[38:31 - 38:32]
+};
+
+template<typename Q>
+struct Derived5: Outer::Inner<Q>::Parm::InnerIterator
+{
+ Derived5() : Outer::Inner<Q>::Parm::InnerIterator() {}
+// CHECK: TypeRef=struct Outer:28:8 Extent=[47:18 - 47:23]
+// CHECK: TemplateRef=Inner:30:12 Extent=[47:25 - 47:30]
+// CHECK: TypeRef=Q:44:19 Extent=[47:31 - 47:32]
+};
+
+template<typename Q>
+struct Derived6: Outer::Inner<Q>
+{
+ Derived6() : Outer::Inner<Q>() {}
+// CHECK: TypeRef=struct Outer:28:8 Extent=[56:18 - 56:23]
+// CHECK: TemplateRef=Inner:30:12 Extent=[56:25 - 56:30]
+// CHECK: TypeRef=Q:53:19 Extent=[56:31 - 56:32]
+};
+
+struct Base {};
+
+struct Derived7: Outer::Inner<Base>::Parm
+{
+ Derived7() : Outer::Inner<Base>::Parm() {}
+// CHECK: TypeRef=struct Outer:28:8 Extent=[66:18 - 66:23]
+// CHECK: TemplateRef=Inner:30:12 Extent=[66:25 - 66:30]
+// CHECK: TypeRef=struct Base:62:8 Extent=[66:31 - 66:35]
+};
+
+struct Derived8: Outer::Inner<Base>
+{
+ Derived8() : Outer::Inner<Base>() {}
+// CHECK: TypeRef=struct Outer:28:8 Extent=[74:18 - 74:23]
+// CHECK: TemplateRef=Inner:30:12 Extent=[74:25 - 74:30]
+// CHECK: TypeRef=struct Base:62:8 Extent=[74:31 - 74:35]
+};
+
+namespace Namespace {
+ template<typename Q> struct Templ;
+
+ struct Outer {
+ template <typename Q>
+ struct Inner {
+ typedef Q Parm;
+ };
+ };
+}
+
+template<typename MyBase>
+struct Derived9: Namespace::Templ<MyBase>::InnerIterator
+{
+ Derived9() : Namespace::Templ<MyBase>::InnerIterator() {}
+// CHECK: NamespaceRef=Namespace:80:11 Extent=[94:18 - 94:27]
+// CHECK: TemplateRef=Templ:81:33 Extent=[94:29 - 94:34]
+// CHECK: TypeRef=MyBase:91:19 Extent=[94:35 - 94:41]
+};
+
+template<typename MyBase>
+struct Derived10: Namespace::Templ<MyBase>
+{
+ Derived10() : Namespace::Templ<MyBase>() {}
+// CHECK: NamespaceRef=Namespace:80:11 Extent=[103:19 - 103:28]
+// CHECK: TemplateRef=Templ:81:33 Extent=[103:30 - 103:35]
+// CHECK: TypeRef=MyBase:100:19 Extent=[103:36 - 103:42]
+};
+
+template<typename MyBase>
+struct Derived11: Namespace::Outer::Inner<MyBase>::Parm
+{
+ Derived11() : Namespace::Outer::Inner<MyBase>::Parm() {}
+// CHECK: NamespaceRef=Namespace:80:11 Extent=[112:19 - 112:28]
+// CHECK: TypeRef=struct Namespace::Outer:83:12 Extent=[112:30 - 112:35]
+// CHECK: TemplateRef=Inner:85:16 Extent=[112:37 - 112:42]
+// CHECK: TypeRef=MyBase:109:19 Extent=[112:43 - 112:49]
+};
diff --git a/test/Index/get-cursor.cpp b/test/Index/get-cursor.cpp
index 27f75938fedd..8aa12d5bc310 100644
--- a/test/Index/get-cursor.cpp
+++ b/test/Index/get-cursor.cpp
@@ -145,6 +145,13 @@ void test(TestColl coll) {
const int operator""_toint(unsigned long long val) { return int(val); }
+// noexcept specifications
+void f_noexcept() noexcept;
+template <class T> void f_computed_noexcept(T t) noexcept(noexcept(t+t));
+void f_dynamic_noexcept_none() throw();
+void f_dynamic_noexcept() throw(int);
+void f_dynamic_noexcept_any() throw(...);
+
// RUN: c-index-test -cursor-at=%s:6:4 %s | FileCheck -check-prefix=CHECK-COMPLETION-1 %s
// CHECK-COMPLETION-1: CXXConstructor=X:6:3
// CHECK-COMPLETION-1-NEXT: Completion string: {TypedText X}{LeftParen (}{Placeholder int}{Comma , }{Placeholder int}{RightParen )}
@@ -209,11 +216,11 @@ const int operator""_toint(unsigned long long val) { return int(val); }
// RUN: c-index-test -cursor-at=%s:66:23 %s | FileCheck -check-prefix=CHECK-TEMPLSPEC %s
// CHECK-TEMPLSPEC: 66:23 ClassDecl=TC:66:23 (Definition) [Specialization of TC:59:7] Extent=[66:1 - 66:31] Spelling=TC ([66:23 - 66:25])
-// RUN: c-index-test -cursor-at=%s:69:3 -cursor-at=%s:70:11 -cursor-at=%s:73:6 -cursor-at=%s:74:6 -cursor-at=%s:77:8 -cursor-at=%s:78:8 -cursor-at=%s:79:8 -cursor-at=%s:80:8 -cursor-at=%s:81:8 -cursor-at=%s:82:8 -cursor-at=%s:85:6 -cursor-at=%s:86:6 -cursor-at=%s:87:6 -cursor-at=%s:88:6 -cursor-at=%s:91:5 -cursor-at=%s:92:5 -cursor-at=%s:93:5 -cursor-at=%s:94:5 -cursor-at=%s:95:5 -cursor-at=%s:96:5 -cursor-at=%s:97:5 -cursor-at=%s:98:5 -cursor-at=%s:100:5 -cursor-at=%s:101:5 -cursor-at=%s:104:6 -cursor-at=%s:105:6 -cursor-at=%s:106:6 -cursor-at=%s:107:6 -cursor-at=%s:108:6 -cursor-at=%s:109:6 -cursor-at=%s:110:6 -cursor-at=%s:111:6 -cursor-at=%s:113:6 -cursor-at=%s:114:6 -cursor-at=%s:117:8 -cursor-at=%s:118:8 -cursor-at=%s:120:8 -cursor-at=%s:121:8 -cursor-at=%s:122:8 -cursor-at=%s:123:8 -cursor-at=%s:124:8 -cursor-at=%s:125:8 -cursor-at=%s:128:6 -cursor-at=%s:129:6 -cursor-at=%s:130:6 -cursor-at=%s:132:3 -cursor-at=%s:146:15 -std=c++11 %s | FileCheck -check-prefix=CHECK-SPELLING %s
+// RUN: c-index-test -cursor-at=%s:69:3 -cursor-at=%s:70:11 -cursor-at=%s:73:6 -cursor-at=%s:74:6 -cursor-at=%s:77:8 -cursor-at=%s:78:8 -cursor-at=%s:79:8 -cursor-at=%s:80:8 -cursor-at=%s:81:8 -cursor-at=%s:82:8 -cursor-at=%s:85:6 -cursor-at=%s:86:6 -cursor-at=%s:87:6 -cursor-at=%s:88:6 -cursor-at=%s:91:5 -cursor-at=%s:92:5 -cursor-at=%s:93:5 -cursor-at=%s:94:5 -cursor-at=%s:95:5 -cursor-at=%s:96:5 -cursor-at=%s:97:5 -cursor-at=%s:98:5 -cursor-at=%s:100:5 -cursor-at=%s:101:5 -cursor-at=%s:104:6 -cursor-at=%s:105:6 -cursor-at=%s:106:6 -cursor-at=%s:107:6 -cursor-at=%s:108:6 -cursor-at=%s:109:6 -cursor-at=%s:110:6 -cursor-at=%s:111:6 -cursor-at=%s:113:6 -cursor-at=%s:114:6 -cursor-at=%s:117:8 -cursor-at=%s:118:8 -cursor-at=%s:120:8 -cursor-at=%s:121:8 -cursor-at=%s:122:8 -cursor-at=%s:123:8 -cursor-at=%s:124:8 -cursor-at=%s:125:8 -cursor-at=%s:128:6 -cursor-at=%s:129:6 -cursor-at=%s:130:6 -cursor-at=%s:132:3 -cursor-at=%s:146:15 -cursor-at=%s:149:6 -cursor-at=%s:150:25 -cursor-at=%s:151:6 -cursor-at=%s:152:6 -cursor-at=%s:153:6 -std=c++11 %s | FileCheck -check-prefix=CHECK-SPELLING %s
// CHECK-SPELLING: 69:3 CXXConstructor=A:69:3 (default constructor) Extent=[69:3 - 69:6] Spelling=A ([69:3 - 69:4])
// CHECK-SPELLING: 70:11 CXXDestructor=~A:70:11 (virtual) Extent=[70:3 - 70:15] Spelling=~A ([70:11 - 70:13])
// CHECK-SPELLING: 73:6 CXXMethod=operator=:73:6 Extent=[73:3 - 73:25] Spelling=operator= ([73:6 - 73:15])
-// CHECK-SPELLING: 74:6 CXXMethod=operator=:74:6 Extent=[74:3 - 74:29] Spelling=operator= ([74:6 - 74:15])
+// CHECK-SPELLING: 74:6 CXXMethod=operator=:74:6 (noexcept) Extent=[74:3 - 74:29] Spelling=operator= ([74:6 - 74:15])
// CHECK-SPELLING: 77:8 CXXMethod=operator+:77:8 (const) Extent=[77:3 - 77:25] Spelling=operator+ ([77:8 - 77:17])
// CHECK-SPELLING: 78:8 CXXMethod=operator-:78:8 (const) Extent=[78:3 - 78:25] Spelling=operator- ([78:8 - 78:17])
// CHECK-SPELLING: 79:8 CXXMethod=operator~:79:8 (const) Extent=[79:3 - 79:25] Spelling=operator~ ([79:8 - 79:17])
@@ -257,8 +264,14 @@ const int operator""_toint(unsigned long long val) { return int(val); }
// CHECK-SPELLING: 130:6 CXXMethod=operator():130:6 (const) Extent=[130:3 - 130:37] Spelling=operator() ([130:6 - 130:16])
// CHECK-SPELLING: 132:12 CXXConversion=operator bool:132:12 (const) Extent=[132:3 - 132:33] Spelling=operator bool ([132:12 - 132:25])
// CHECK-SPELLING: 146:11 FunctionDecl=operator""_toint:146:11 (Definition) Extent=[146:1 - 146:72] Spelling=operator""_toint ([146:11 - 146:27])
+// CHECK-SPELLING: 149:6 FunctionDecl=f_noexcept:149:6 (noexcept) Extent=[149:1 - 149:27] Spelling=f_noexcept ([149:6 - 149:16])
+// CHECK-SPELLING: 150:25 FunctionTemplate=f_computed_noexcept:150:25 (computed-noexcept) Extent=[150:1 - 150:73] Spelling=f_computed_noexcept ([150:25 - 150:44])
+// CHECK-SPELLING: 151:6 FunctionDecl=f_dynamic_noexcept_none:151:6 (noexcept dynamic none) Extent=[151:1 - 151:39] Spelling=f_dynamic_noexcept_none ([151:6 - 151:29])
+// CHECK-SPELLING: 152:6 FunctionDecl=f_dynamic_noexcept:152:6 (noexcept dynamic) Extent=[152:1 - 152:37] Spelling=f_dynamic_noexcept ([152:6 - 152:24])
+// CHECK-SPELLING: 153:6 FunctionDecl=f_dynamic_noexcept_any:153:6 (noexcept dynamic any) Extent=[153:1 - 153:41] Spelling=f_dynamic_noexcept_any ([153:6 - 153:28])
// RUN: c-index-test -cursor-at=%s:141:13 -cursor-at=%s:141:18 -cursor-at=%s:142:11 -std=c++11 %s | FileCheck -check-prefix=CHECK-FORRANGE %s
// CHECK-FORRANGE: 141:13 VarDecl=lv:141:13 (Definition) Extent=[141:8 - 141:17] Spelling=lv ([141:13 - 141:15])
// CHECK-FORRANGE: 141:18 DeclRefExpr=coll:140:20 Extent=[141:18 - 141:22] Spelling=coll ([141:18 - 141:22])
// CHECK-FORRANGE: 142:11 DeclRefExpr=lv:141:13 Extent=[142:11 - 142:13] Spelling=lv ([142:11 - 142:13])
+
diff --git a/test/Index/linkage.c b/test/Index/linkage.c
index ab006590b61c..b0dcb30990a0 100644
--- a/test/Index/linkage.c
+++ b/test/Index/linkage.c
@@ -20,7 +20,7 @@ void f16(void) {
// CHECK: EnumDecl=Baz:3:6 (Definition)linkage=External
-// CHECK: EnumConstantDecl=Qux:3:12 (Definition)linkage=External
+// CHECK: EnumConstantDecl=Qux:3:12 (Definition)linkage=NoLinkage
// CHECK: VarDecl=x:4:5linkage=External
// CHECK: FunctionDecl=foo:5:6linkage=External
// CHECK: VarDecl=w:6:12linkage=Internal
diff --git a/test/Modules/Inputs/F.framework/Headers/F.h b/test/Modules/Inputs/F.framework/Headers/F.h
new file mode 100644
index 000000000000..4f705f00e1ac
--- /dev/null
+++ b/test/Modules/Inputs/F.framework/Headers/F.h
@@ -0,0 +1 @@
+// F.h
diff --git a/test/Modules/Inputs/F.framework/Modules/module.modulemap b/test/Modules/Inputs/F.framework/Modules/module.modulemap
new file mode 100644
index 000000000000..e414776c536b
--- /dev/null
+++ b/test/Modules/Inputs/F.framework/Modules/module.modulemap
@@ -0,0 +1,7 @@
+framework module F [extern_c] [system] {
+ umbrella header "F.h"
+ module * {
+ export *
+ }
+ export *
+}
diff --git a/test/Modules/Inputs/F.framework/Modules/module.private.modulemap b/test/Modules/Inputs/F.framework/Modules/module.private.modulemap
new file mode 100644
index 000000000000..69486a2a6410
--- /dev/null
+++ b/test/Modules/Inputs/F.framework/Modules/module.private.modulemap
@@ -0,0 +1,7 @@
+module F.Private [system] {
+ explicit module NS {
+ header "NS.h"
+ export *
+ }
+ export *
+}
diff --git a/test/Modules/Inputs/F.framework/PrivateHeaders/NS.h b/test/Modules/Inputs/F.framework/PrivateHeaders/NS.h
new file mode 100644
index 000000000000..5e947ba90518
--- /dev/null
+++ b/test/Modules/Inputs/F.framework/PrivateHeaders/NS.h
@@ -0,0 +1,19 @@
+struct NS {
+ int a;
+ int b;
+};
+
+enum NSE {
+ FST = 22,
+ SND = 43,
+ TRD = 55
+};
+
+#define NS_ENUM(_type, _name) \
+ enum _name : _type _name; \
+ enum _name : _type
+
+typedef NS_ENUM(int, NSMyEnum) {
+ MinX = 11,
+ MinXOther = MinX,
+};
diff --git a/test/Modules/Inputs/lookup-assert-protocol/Base.h b/test/Modules/Inputs/lookup-assert-protocol/Base.h
new file mode 100644
index 000000000000..5c9506fa5cd3
--- /dev/null
+++ b/test/Modules/Inputs/lookup-assert-protocol/Base.h
@@ -0,0 +1,3 @@
+@protocol BaseProtocol
+- (void) test;
+@end
diff --git a/test/Modules/Inputs/lookup-assert-protocol/Derive.h b/test/Modules/Inputs/lookup-assert-protocol/Derive.h
new file mode 100644
index 000000000000..fdcde6158a7c
--- /dev/null
+++ b/test/Modules/Inputs/lookup-assert-protocol/Derive.h
@@ -0,0 +1,4 @@
+#include "Base.h"
+@protocol DerivedProtocol<BaseProtocol>
+- (void) test2;
+@end
diff --git a/test/Modules/Inputs/lookup-assert-protocol/H3.h b/test/Modules/Inputs/lookup-assert-protocol/H3.h
new file mode 100644
index 000000000000..3d8f878905df
--- /dev/null
+++ b/test/Modules/Inputs/lookup-assert-protocol/H3.h
@@ -0,0 +1 @@
+#include "Base.h"
diff --git a/test/Modules/Inputs/lookup-assert-protocol/module.map b/test/Modules/Inputs/lookup-assert-protocol/module.map
new file mode 100644
index 000000000000..e8a89eb095a4
--- /dev/null
+++ b/test/Modules/Inputs/lookup-assert-protocol/module.map
@@ -0,0 +1,4 @@
+module X {
+ header "H3.h"
+ export *
+}
diff --git a/test/Modules/Inputs/preprocess-decluse/a.h b/test/Modules/Inputs/preprocess-decluse/a.h
new file mode 100644
index 000000000000..17ab46c84892
--- /dev/null
+++ b/test/Modules/Inputs/preprocess-decluse/a.h
@@ -0,0 +1 @@
+// a.h
diff --git a/test/Modules/Inputs/preprocess-decluse/a.modulemap b/test/Modules/Inputs/preprocess-decluse/a.modulemap
new file mode 100644
index 000000000000..47105fe36399
--- /dev/null
+++ b/test/Modules/Inputs/preprocess-decluse/a.modulemap
@@ -0,0 +1 @@
+module A { textual header "a.h" }
diff --git a/test/Modules/Inputs/preprocess-decluse/b.h b/test/Modules/Inputs/preprocess-decluse/b.h
new file mode 100644
index 000000000000..2243de1baf9a
--- /dev/null
+++ b/test/Modules/Inputs/preprocess-decluse/b.h
@@ -0,0 +1 @@
+#include "a.h"
diff --git a/test/Modules/Inputs/preprocess-decluse/b.modulemap b/test/Modules/Inputs/preprocess-decluse/b.modulemap
new file mode 100644
index 000000000000..bd0bdf0e2e94
--- /dev/null
+++ b/test/Modules/Inputs/preprocess-decluse/b.modulemap
@@ -0,0 +1 @@
+module B { header "b.h" use A }
diff --git a/test/Modules/Inputs/preprocess-decluse/main.modulemap b/test/Modules/Inputs/preprocess-decluse/main.modulemap
new file mode 100644
index 000000000000..0392c846ce99
--- /dev/null
+++ b/test/Modules/Inputs/preprocess-decluse/main.modulemap
@@ -0,0 +1 @@
+module Main { use B }
diff --git a/test/Modules/diag-flags.cpp b/test/Modules/diag-flags.cpp
index 31d2fe4439b8..ada90d24b791 100644
--- a/test/Modules/diag-flags.cpp
+++ b/test/Modules/diag-flags.cpp
@@ -41,4 +41,4 @@ import diag_flags;
#else
// expected-no-diagnostics
#endif
-unsigned n = sizeof(Padded);
+int arr[sizeof(Padded)];
diff --git a/test/Modules/elaborated-type-specifier-from-hidden-module.m b/test/Modules/elaborated-type-specifier-from-hidden-module.m
index 0ca1c24bba00..571ccb9d95c0 100644
--- a/test/Modules/elaborated-type-specifier-from-hidden-module.m
+++ b/test/Modules/elaborated-type-specifier-from-hidden-module.m
@@ -4,12 +4,11 @@
@import ElaboratedTypeStructs.Empty; // The structs are now hidden.
struct S1 *x;
struct S2 *y;
-// FIXME: compatible definition should not be an error.
-struct S2 { int x; }; // expected-error {{redefinition}}
+struct S2 { int x; };
struct S3 *z;
// Incompatible definition.
-struct S3 { float y; }; // expected-error {{redefinition}}
-// expected-note@elaborated-type-structs.h:* 2 {{previous definition is here}}
+struct S3 { float y; }; // expected-error {{has incompatible definitions}} // expected-note {{field has name}}
+// expected-note@Inputs/elaborated-type-structs.h:3 {{field has name}}
@import ElaboratedTypeStructs.Structs;
diff --git a/test/Modules/lookup-assert-protocol.m b/test/Modules/lookup-assert-protocol.m
new file mode 100644
index 000000000000..3c093f1bf156
--- /dev/null
+++ b/test/Modules/lookup-assert-protocol.m
@@ -0,0 +1,17 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -I %S/Inputs/lookup-assert-protocol %s -verify
+// expected-no-diagnostics
+
+#include "Derive.h"
+#import <H3.h>
+
+__attribute__((objc_root_class))
+@interface Thing<DerivedProtocol>
+@end
+
+@implementation Thing
+- (void)test {
+}
+- (void)test2 {
+}
+@end
diff --git a/test/Modules/odr_hash.cpp b/test/Modules/odr_hash.cpp
index c94940c73eb6..6e01e989a374 100644
--- a/test/Modules/odr_hash.cpp
+++ b/test/Modules/odr_hash.cpp
@@ -968,6 +968,24 @@ S9 s9;
// expected-error@second.h:* {{'NestedNamespaceSpecifier::S9' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'x' with type 'P9::I' (aka 'int')}}
// expected-note@first.h:* {{but in 'FirstModule' found field 'x' with type 'O9::I' (aka 'int')}}
#endif
+
+namespace N10 {
+#if defined(FIRST)
+inline namespace A { struct X {}; }
+struct S10 {
+ A::X x;
+};
+#elif defined(SECOND)
+inline namespace B { struct X {}; }
+struct S10 {
+ B::X x;
+};
+#else
+S10 s10;
+// expected-error@second.h:* {{'NestedNamespaceSpecifier::N10::S10::x' from module 'SecondModule' is not present in definition of 'NestedNamespaceSpecifier::N10::S10' in module 'FirstModule'}}
+// expected-note@first.h:* {{declaration of 'x' does not match}}
+#endif
+}
}
namespace TemplateSpecializationType {
@@ -1070,6 +1088,40 @@ S4 s4;
// expected-error@first.h:* {{'TemplateArgument::S4::x' from module 'FirstModule' is not present in definition of 'TemplateArgument::S4' in module 'SecondModule'}}
// expected-note@second.h:* {{declaration of 'x' does not match}}
#endif
+
+#if defined(FIRST)
+template <class T> struct U5 {};
+struct S5 {
+ U5<int> x;
+};
+#elif defined(SECOND)
+template <class T> struct U5 {};
+struct S5 {
+ U5<short> x;
+};
+#else
+S5 s5;
+// expected-error@first.h:* {{'TemplateArgument::S5::x' from module 'FirstModule' is not present in definition of 'TemplateArgument::S5' in module 'SecondModule'}}
+// expected-note@second.h:* {{declaration of 'x' does not match}}
+#endif
+
+#if defined(FIRST)
+template <class T> struct U6 {};
+struct S6 {
+ U6<int> x;
+ U6<short> y;
+};
+#elif defined(SECOND)
+template <class T> struct U6 {};
+struct S6 {
+ U6<short> y;
+ U6<int> x;
+};
+#else
+S6 s6;
+// expected-error@second.h:* {{'TemplateArgument::S6' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'y'}}
+// expected-note@first.h:* {{but in 'FirstModule' found field 'x'}}
+#endif
}
namespace TemplateTypeParmType {
@@ -1762,6 +1814,22 @@ struct S2 {
#else
S2 s2;
#endif
+
+#if defined(FIRST)
+using A3 = const int;
+using B3 = volatile A3;
+struct S3 {
+ B3 x = 1;
+};
+#elif defined(SECOND)
+using A3 = volatile const int;
+using B3 = A3;
+struct S3 {
+ B3 x = 1;
+};
+#else
+S3 s3;
+#endif
}
// Keep macros contained to one file.
diff --git a/test/Modules/preprocess-decluse.cpp b/test/Modules/preprocess-decluse.cpp
new file mode 100644
index 000000000000..5c87e0dddac2
--- /dev/null
+++ b/test/Modules/preprocess-decluse.cpp
@@ -0,0 +1,18 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules -fmodules-strict-decluse -I%S/Inputs/preprocess-decluse \
+// RUN: -fmodule-name=B -emit-module -o %t/b.pcm \
+// RUN: -fmodule-map-file=%S/Inputs/preprocess-decluse/a.modulemap \
+// RUN: -x c++-module-map %S/Inputs/preprocess-decluse/b.modulemap
+// RUN: %clang_cc1 -fmodules -fmodules-strict-decluse -I%S/Inputs/preprocess-decluse \
+// RUN: -fmodule-map-file=%S/Inputs/preprocess-decluse/main.modulemap \
+// RUN: -fmodule-file=%t/b.pcm -fmodule-name=Main %s -verify
+// RUN: %clang_cc1 -fmodules -fmodules-strict-decluse -I%S/Inputs/preprocess-decluse \
+// RUN: -fmodule-map-file=%S/Inputs/preprocess-decluse/main.modulemap \
+// RUN: -fmodule-file=%t/b.pcm -fmodule-name=Main %s \
+// RUN: -E -frewrite-imports -o %t/rewrite.ii
+// RUN: %clang_cc1 -fmodules -fmodules-strict-decluse -I%S/Inputs/preprocess-decluse \
+// RUN: -fmodule-map-file=%S/Inputs/preprocess-decluse/main.modulemap \
+// RUN: -fmodule-name=Main %t/rewrite.ii -verify
+
+// expected-no-diagnostics
+#include "b.h"
diff --git a/test/Modules/redefinition-c-tagtypes.m b/test/Modules/redefinition-c-tagtypes.m
new file mode 100644
index 000000000000..a01f11bd74c8
--- /dev/null
+++ b/test/Modules/redefinition-c-tagtypes.m
@@ -0,0 +1,48 @@
+// RUN: rm -rf %t.cache
+// RUN: %clang_cc1 -fsyntax-only %s -fmodules -fmodules-cache-path=%t.cache \
+// RUN: -fimplicit-module-maps -F%S/Inputs -verify
+// RUN: %clang_cc1 -fsyntax-only %s -fmodules -fmodules-cache-path=%t.cache \
+// RUN: -fimplicit-module-maps -F%S/Inputs -DCHANGE_TAGS -verify
+#include "F/F.h"
+
+#ifndef CHANGE_TAGS
+// expected-no-diagnostics
+#endif
+
+struct NS {
+ int a;
+#ifndef CHANGE_TAGS
+ int b;
+#else
+ int c; // expected-note {{field has name 'c' here}}
+ // expected-error@redefinition-c-tagtypes.m:12 {{type 'struct NS' has incompatible definitions}}
+ // expected-note@Inputs/F.framework/PrivateHeaders/NS.h:3 {{field has name 'b' here}}
+#endif
+};
+
+enum NSE {
+ FST = 22,
+#ifndef CHANGE_TAGS
+ SND = 43,
+#else
+ SND = 44, // expected-note {{enumerator 'SND' with value 44 here}}
+ // expected-error@redefinition-c-tagtypes.m:23 {{type 'enum NSE' has incompatible definitions}}
+ // expected-note@Inputs/F.framework/PrivateHeaders/NS.h:8 {{enumerator 'SND' with value 43 here}}
+#endif
+ TRD = 55
+};
+
+#define NS_ENUM(_type, _name) \
+ enum _name : _type _name; \
+ enum _name : _type
+
+typedef NS_ENUM(int, NSMyEnum) {
+ MinX = 11,
+#ifndef CHANGE_TAGS
+ MinXOther = MinX,
+#else
+ MinXOther = TRD, // expected-note {{enumerator 'MinXOther' with value 55 here}}
+ // expected-error@redefinition-c-tagtypes.m:39 {{type 'enum NSMyEnum' has incompatible definitions}}
+ // expected-note@Inputs/F.framework/PrivateHeaders/NS.h:18 {{enumerator 'MinXOther' with value 11 here}}
+#endif
+};
diff --git a/test/Modules/redefinition-same-header.m b/test/Modules/redefinition-same-header.m
index f1c6cbbcaa2e..8c180f643225 100644
--- a/test/Modules/redefinition-same-header.m
+++ b/test/Modules/redefinition-same-header.m
@@ -6,15 +6,7 @@
// expected-note-re@Inputs/SameHeader/B.h:3 {{'{{.*}}C.h' included multiple times, additional include site in header from module 'X.B'}}
// expected-note@Inputs/SameHeader/module.modulemap:6 {{X.B defined here}}
// expected-note-re@redefinition-same-header.m:20 {{'{{.*}}C.h' included multiple times, additional include site here}}
+// expected-warning@Inputs/SameHeader/C.h:9 {{typedef requires a name}}
-// expected-error@Inputs/SameHeader/C.h:5 {{redefinition of 'aaa'}}
-// expected-note-re@Inputs/SameHeader/B.h:3 {{'{{.*}}C.h' included multiple times, additional include site in header from module 'X.B'}}
-// expected-note@Inputs/SameHeader/module.modulemap:6 {{X.B defined here}}
-// expected-note-re@redefinition-same-header.m:20 {{'{{.*}}C.h' included multiple times, additional include site here}}
-
-// expected-error@Inputs/SameHeader/C.h:9 {{redefinition of 'fd_set'}}
-// expected-note-re@Inputs/SameHeader/B.h:3 {{'{{.*}}C.h' included multiple times, additional include site in header from module 'X.B'}}
-// expected-note@Inputs/SameHeader/module.modulemap:6 {{X.B defined here}}
-// expected-note-re@redefinition-same-header.m:20 {{'{{.*}}C.h' included multiple times, additional include site here}}
#include "A.h" // maps to a modular
#include "C.h" // textual include
diff --git a/test/OpenMP/parallel_codegen.cpp b/test/OpenMP/parallel_codegen.cpp
index c43533c6c194..23b323778b47 100644
--- a/test/OpenMP/parallel_codegen.cpp
+++ b/test/OpenMP/parallel_codegen.cpp
@@ -64,7 +64,7 @@ int main (int argc, char **argv) {
// CHECK: call {{.*}}void @{{.+terminate.*|abort}}(
// CHECK-NEXT: unreachable
// CHECK-NEXT: }
-// CHECK-DEBUG: define internal void [[OMP_OUTLINED]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i64 [[VLA_SIZE:%.+]], i32* [[VLA_ADDR:%[^)]+]])
+// CHECK-DEBUG: define internal void [[OMP_OUTLINED_DEBUG:@.+]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i64 [[VLA_SIZE:%.+]], i32* [[VLA_ADDR:%[^)]+]])
// CHECK-DEBUG-SAME: #[[FN_ATTRS:[0-9]+]]
// CHECK-DEBUG: store i32* [[VLA_ADDR]], i32** [[VLA_PTR_ADDR:%.+]],
// CHECK-DEBUG: [[VLA_REF:%.+]] = load i32*, i32** [[VLA_PTR_ADDR]]
@@ -80,6 +80,8 @@ int main (int argc, char **argv) {
// CHECK-DAG: declare {{.*}}void @__kmpc_fork_call(%ident_t*, i32, void (i32*, i32*, ...)*, ...)
// CHECK-DEBUG-DAG: define linkonce_odr void [[FOO]](i32 %argc)
// CHECK-DEBUG-DAG: declare void @__kmpc_fork_call(%ident_t*, i32, void (i32*, i32*, ...)*, ...)
+// CHECK-DEBUG-DAG: define internal void [[OMP_OUTLINED]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i64 [[VLA_SIZE:%.+]], i32* [[VLA_ADDR:%[^)]+]])
+// CHECK-DEBUG-DAG: call void [[OMP_OUTLINED_DEBUG]]
// CHECK: define linkonce_odr {{[a-z\_\b]*[ ]?i32}} [[TMAIN]](i8** %argc)
// CHECK: store i8** %argc, i8*** [[ARGC_ADDR:%.+]],
diff --git a/test/OpenMP/target_codegen.cpp b/test/OpenMP/target_codegen.cpp
index aaaf5fae5729..c457045c17c7 100644
--- a/test/OpenMP/target_codegen.cpp
+++ b/test/OpenMP/target_codegen.cpp
@@ -117,10 +117,10 @@ int foo(int n) {
// CHECK-DAG: [[P]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[PR:%[^,]+]], i32 0, i32 0
// CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[BPR]], i32 0, i32 [[IDX0:[0-9]+]]
// CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[PR]], i32 0, i32 [[IDX0]]
- // CHECK-DAG: store i8* [[BP0:%[^,]+]], i8** [[BPADDR0]]
- // CHECK-DAG: store i8* [[P0:%[^,]+]], i8** [[PADDR0]]
- // CHECK-DAG: [[BP0]] = inttoptr i[[SZ]] %{{.+}} to i8*
- // CHECK-DAG: [[P0]] = inttoptr i[[SZ]] %{{.+}} to i8*
+ // CHECK-DAG: [[CBPADDR0:%.+]] = bitcast i8** [[BPADDR0]] to i[[SZ]]*
+ // CHECK-DAG: [[CPADDR0:%.+]] = bitcast i8** [[PADDR0]] to i[[SZ]]*
+ // CHECK-DAG: store i[[SZ]] [[BP0:%[^,]+]], i[[SZ]]* [[CBPADDR0]]
+ // CHECK-DAG: store i[[SZ]] [[P0:%[^,]+]], i[[SZ]]* [[CPADDR0]]
// CHECK: store i32 [[RET]], i32* [[RHV:%.+]], align 4
// CHECK: [[RET2:%.+]] = load i32, i32* [[RHV]], align 4
@@ -144,17 +144,17 @@ int foo(int n) {
// CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP]], i32 0, i32 0
// CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[P]], i32 0, i32 0
- // CHECK-DAG: store i8* [[BP0:%[^,]+]], i8** [[BPADDR0]]
- // CHECK-DAG: store i8* [[P0:%[^,]+]], i8** [[PADDR0]]
- // CHECK-DAG: [[BP0]] = inttoptr i[[SZ]] %{{.+}} to i8*
- // CHECK-DAG: [[P0]] = inttoptr i[[SZ]] %{{.+}} to i8*
+ // CHECK-DAG: [[CBPADDR0:%.+]] = bitcast i8** [[BPADDR0]] to i[[SZ]]*
+ // CHECK-DAG: [[CPADDR0:%.+]] = bitcast i8** [[PADDR0]] to i[[SZ]]*
+ // CHECK-DAG: store i[[SZ]] [[BP0:%[^,]+]], i[[SZ]]* [[CBPADDR0]]
+ // CHECK-DAG: store i[[SZ]] [[P0:%[^,]+]], i[[SZ]]* [[CPADDR0]]
// CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP]], i32 0, i32 1
// CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[P]], i32 0, i32 1
- // CHECK-DAG: store i8* [[BP1:%[^,]+]], i8** [[BPADDR1]]
- // CHECK-DAG: store i8* [[P1:%[^,]+]], i8** [[PADDR1]]
- // CHECK-DAG: [[BP1]] = inttoptr i[[SZ]] %{{.+}} to i8*
- // CHECK-DAG: [[P1]] = inttoptr i[[SZ]] %{{.+}} to i8*
+ // CHECK-DAG: [[CBPADDR1:%.+]] = bitcast i8** [[BPADDR1]] to i[[SZ]]*
+ // CHECK-DAG: [[CPADDR1:%.+]] = bitcast i8** [[PADDR1]] to i[[SZ]]*
+ // CHECK-DAG: store i[[SZ]] [[BP1:%[^,]+]], i[[SZ]]* [[CBPADDR1]]
+ // CHECK-DAG: store i[[SZ]] [[P1:%[^,]+]], i[[SZ]]* [[CPADDR1]]
// CHECK: store i32 [[RET]], i32* [[RHV:%.+]], align 4
// CHECK-NEXT: br label %[[IFEND:.+]]
@@ -198,87 +198,89 @@ int foo(int n) {
// CHECK-DAG: [[PR]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[P:%[^,]+]], i32 0, i32 0
// CHECK-DAG: [[SR]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S:%[^,]+]], i32 0, i32 0
- // CHECK-DAG: [[SADDR0:%.+]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX0:[0-9]+]]
+ // CHECK-DAG: [[SADDR0:%.+]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX0:0]]
// CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BP]], i32 0, i32 [[IDX0]]
// CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[P]], i32 0, i32 [[IDX0]]
- // CHECK-DAG: [[SADDR1:%.+]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX1:[0-9]+]]
+ // CHECK-DAG: [[SADDR1:%.+]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX1:1]]
// CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BP]], i32 0, i32 [[IDX1]]
// CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[P]], i32 0, i32 [[IDX1]]
- // CHECK-DAG: [[SADDR2:%.+]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX2:[0-9]+]]
+ // CHECK-DAG: [[SADDR2:%.+]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX2:2]]
// CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BP]], i32 0, i32 [[IDX2]]
// CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[P]], i32 0, i32 [[IDX2]]
- // CHECK-DAG: [[SADDR3:%.+]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX3:[0-9]+]]
+ // CHECK-DAG: [[SADDR3:%.+]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX3:3]]
// CHECK-DAG: [[BPADDR3:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BP]], i32 0, i32 [[IDX3]]
// CHECK-DAG: [[PADDR3:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[P]], i32 0, i32 [[IDX3]]
- // CHECK-DAG: [[SADDR4:%.+]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX4:[0-9]+]]
+ // CHECK-DAG: [[SADDR4:%.+]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX4:4]]
// CHECK-DAG: [[BPADDR4:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BP]], i32 0, i32 [[IDX4]]
// CHECK-DAG: [[PADDR4:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[P]], i32 0, i32 [[IDX4]]
- // CHECK-DAG: [[SADDR5:%.+]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX5:[0-9]+]]
+ // CHECK-DAG: [[SADDR5:%.+]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX5:5]]
// CHECK-DAG: [[BPADDR5:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BP]], i32 0, i32 [[IDX5]]
// CHECK-DAG: [[PADDR5:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[P]], i32 0, i32 [[IDX5]]
- // CHECK-DAG: [[SADDR6:%.+]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX6:[0-9]+]]
+ // CHECK-DAG: [[SADDR6:%.+]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX6:6]]
// CHECK-DAG: [[BPADDR6:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BP]], i32 0, i32 [[IDX6]]
// CHECK-DAG: [[PADDR6:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[P]], i32 0, i32 [[IDX6]]
- // CHECK-DAG: [[SADDR7:%.+]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX7:[0-9]+]]
+ // CHECK-DAG: [[SADDR7:%.+]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX7:7]]
// CHECK-DAG: [[BPADDR7:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BP]], i32 0, i32 [[IDX7]]
// CHECK-DAG: [[PADDR7:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[P]], i32 0, i32 [[IDX7]]
- // CHECK-DAG: [[SADDR8:%.+]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX8:[0-9]+]]
+ // CHECK-DAG: [[SADDR8:%.+]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX8:8]]
// CHECK-DAG: [[BPADDR8:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BP]], i32 0, i32 [[IDX8]]
// CHECK-DAG: [[PADDR8:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[P]], i32 0, i32 [[IDX8]]
// The names below are not necessarily consistent with the names used for the
// addresses above as some are repeated.
- // CHECK-DAG: [[BP0:%[^,]+]] = inttoptr i[[SZ]] [[VLA0]] to i8*
- // CHECK-DAG: [[P0:%[^,]+]] = inttoptr i[[SZ]] [[VLA0]] to i8*
- // CHECK-DAG: store i8* [[BP0]], i8** {{%[^,]+}}
- // CHECK-DAG: store i8* [[P0]], i8** {{%[^,]+}}
- // CHECK-DAG: store i[[SZ]] {{4|8}}, i[[SZ]]* {{%[^,]+}}
-
- // CHECK-DAG: [[BP1:%[^,]+]] = inttoptr i[[SZ]] [[VLA1]] to i8*
- // CHECK-DAG: [[P1:%[^,]+]] = inttoptr i[[SZ]] [[VLA1]] to i8*
- // CHECK-DAG: store i8* [[BP1]], i8** {{%[^,]+}}
- // CHECK-DAG: store i8* [[P1]], i8** {{%[^,]+}}
- // CHECK-DAG: store i[[SZ]] {{4|8}}, i[[SZ]]* {{%[^,]+}}
-
- // CHECK-DAG: store i8* inttoptr (i[[SZ]] 5 to i8*), i8** {{%[^,]+}}
- // CHECK-DAG: store i8* inttoptr (i[[SZ]] 5 to i8*), i8** {{%[^,]+}}
- // CHECK-DAG: store i[[SZ]] {{4|8}}, i[[SZ]]* {{%[^,]+}}
-
- // CHECK-DAG: [[BP3:%[^,]+]] = inttoptr i[[SZ]] [[A_CVAL]] to i8*
- // CHECK-DAG: [[P3:%[^,]+]] = inttoptr i[[SZ]] [[A_CVAL]] to i8*
- // CHECK-DAG: store i8* [[BP3]], i8** {{%[^,]+}}
- // CHECK-DAG: store i8* [[P3]], i8** {{%[^,]+}}
- // CHECK-DAG: store i[[SZ]] 4, i[[SZ]]* {{%[^,]+}}
-
- // CHECK-DAG: [[BP4:%[^,]+]] = bitcast [10 x float]* %{{.+}} to i8*
- // CHECK-DAG: [[P4:%[^,]+]] = bitcast [10 x float]* %{{.+}} to i8*
- // CHECK-DAG: store i8* [[BP4]], i8** {{%[^,]+}}
- // CHECK-DAG: store i8* [[P4]], i8** {{%[^,]+}}
- // CHECK-DAG: store i[[SZ]] 40, i[[SZ]]* {{%[^,]+}}
-
- // CHECK-DAG: [[BP5:%[^,]+]] = bitcast float* %{{.+}} to i8*
- // CHECK-DAG: [[P5:%[^,]+]] = bitcast float* %{{.+}} to i8*
- // CHECK-DAG: store i8* [[BP5]], i8** {{%[^,]+}}
- // CHECK-DAG: store i8* [[P5]], i8** {{%[^,]+}}
- // CHECK-DAG: store i[[SZ]] [[BNSIZE]], i[[SZ]]* {{%[^,]+}}
-
- // CHECK-DAG: [[BP6:%[^,]+]] = bitcast [5 x [10 x double]]* %{{.+}} to i8*
- // CHECK-DAG: [[P6:%[^,]+]] = bitcast [5 x [10 x double]]* %{{.+}} to i8*
- // CHECK-DAG: store i8* [[BP6]], i8** {{%[^,]+}}
- // CHECK-DAG: store i8* [[P6]], i8** {{%[^,]+}}
- // CHECK-DAG: store i[[SZ]] 400, i[[SZ]]* {{%[^,]+}}
-
- // CHECK-DAG: [[BP7:%[^,]+]] = bitcast double* %{{.+}} to i8*
- // CHECK-DAG: [[P7:%[^,]+]] = bitcast double* %{{.+}} to i8*
- // CHECK-DAG: store i8* [[BP7]], i8** {{%[^,]+}}
- // CHECK-DAG: store i8* [[P7]], i8** {{%[^,]+}}
- // CHECK-DAG: store i[[SZ]] [[CNSIZE]], i[[SZ]]* {{%[^,]+}}
-
- // CHECK-DAG: [[BP8:%[^,]+]] = bitcast [[TT]]* %{{.+}} to i8*
- // CHECK-DAG: [[P8:%[^,]+]] = bitcast [[TT]]* %{{.+}} to i8*
- // CHECK-DAG: store i8* [[BP8]], i8** {{%[^,]+}}
- // CHECK-DAG: store i8* [[P8]], i8** {{%[^,]+}}
- // CHECK-DAG: store i[[SZ]] {{12|16}}, i[[SZ]]* {{%[^,]+}}
+ // CHECK-DAG: [[CBPADDR2:%.+]] = bitcast i8** [[BPADDR2]] to i[[SZ]]*
+ // CHECK-DAG: [[CPADDR2:%.+]] = bitcast i8** [[PADDR2]] to i[[SZ]]*
+ // CHECK-DAG: store i[[SZ]] [[VLA0]], i[[SZ]]* [[CBPADDR2]]
+ // CHECK-DAG: store i[[SZ]] [[VLA0]], i[[SZ]]* [[CPADDR2]]
+ // CHECK-DAG: store i[[SZ]] {{4|8}}, i[[SZ]]* [[SADDR2]]
+
+ // CHECK-DAG: [[CBPADDR6:%.+]] = bitcast i8** [[BPADDR6]] to i[[SZ]]*
+ // CHECK-DAG: [[CPADDR6:%.+]] = bitcast i8** [[PADDR6]] to i[[SZ]]*
+ // CHECK-DAG: store i[[SZ]] [[VLA1]], i[[SZ]]* [[CBPADDR6]]
+ // CHECK-DAG: store i[[SZ]] [[VLA1]], i[[SZ]]* [[CPADDR6]]
+ // CHECK-DAG: store i[[SZ]] {{4|8}}, i[[SZ]]* [[SADDR6]]
+
+ // CHECK-DAG: [[CBPADDR5:%.+]] = bitcast i8** [[BPADDR5]] to i[[SZ]]*
+ // CHECK-DAG: [[CPADDR5:%.+]] = bitcast i8** [[PADDR5]] to i[[SZ]]*
+ // CHECK-DAG: store i[[SZ]] 5, i[[SZ]]* [[CBPADDR5]]
+ // CHECK-DAG: store i[[SZ]] 5, i[[SZ]]* [[CPADDR5]]
+ // CHECK-DAG: store i[[SZ]] {{4|8}}, i[[SZ]]* [[SADDR5]]
+
+ // CHECK-DAG: [[CBPADDR0:%.+]] = bitcast i8** [[BPADDR0]] to i[[SZ]]*
+ // CHECK-DAG: [[CPADDR0:%.+]] = bitcast i8** [[PADDR0]] to i[[SZ]]*
+ // CHECK-DAG: store i[[SZ]] [[A_CVAL]], i[[SZ]]* [[CBPADDR0]]
+ // CHECK-DAG: store i[[SZ]] [[A_CVAL]], i[[SZ]]* [[CPADDR0]]
+ // CHECK-DAG: store i[[SZ]] 4, i[[SZ]]* [[SADDR0]]
+
+ // CHECK-DAG: [[CBPADDR1:%.+]] = bitcast i8** [[BPADDR1]] to [10 x float]**
+ // CHECK-DAG: [[CPADDR1:%.+]] = bitcast i8** [[PADDR1]] to [10 x float]**
+ // CHECK-DAG: store [10 x float]* %{{.+}}, [10 x float]** [[CBPADDR1]]
+ // CHECK-DAG: store [10 x float]* %{{.+}}, [10 x float]** [[CPADDR1]]
+ // CHECK-DAG: store i[[SZ]] 40, i[[SZ]]* [[SADDR1]]
+
+ // CHECK-DAG: [[CBPADDR3:%.+]] = bitcast i8** [[BPADDR3]] to float**
+ // CHECK-DAG: [[CPADDR3:%.+]] = bitcast i8** [[PADDR3]] to float**
+ // CHECK-DAG: store float* %{{.+}}, float** [[CBPADDR3]]
+ // CHECK-DAG: store float* %{{.+}}, float** [[CPADDR3]]
+ // CHECK-DAG: store i[[SZ]] [[BNSIZE]], i[[SZ]]* [[SADDR3]]
+
+ // CHECK-DAG: [[CBPADDR4:%.+]] = bitcast i8** [[BPADDR4]] to [5 x [10 x double]]**
+ // CHECK-DAG: [[CPADDR4:%.+]] = bitcast i8** [[PADDR4]] to [5 x [10 x double]]**
+ // CHECK-DAG: store [5 x [10 x double]]* %{{.+}}, [5 x [10 x double]]** [[CBPADDR4]]
+ // CHECK-DAG: store [5 x [10 x double]]* %{{.+}}, [5 x [10 x double]]** [[CPADDR4]]
+ // CHECK-DAG: store i[[SZ]] 400, i[[SZ]]* [[SADDR4]]
+
+ // CHECK-DAG: [[CBPADDR7:%.+]] = bitcast i8** [[BPADDR7]] to double**
+ // CHECK-DAG: [[CPADDR7:%.+]] = bitcast i8** [[PADDR7]] to double**
+ // CHECK-DAG: store double* %{{.+}}, double** [[CBPADDR7]]
+ // CHECK-DAG: store double* %{{.+}}, double** [[CPADDR7]]
+ // CHECK-DAG: store i[[SZ]] [[CNSIZE]], i[[SZ]]* [[SADDR7]]
+
+ // CHECK-DAG: [[CBPADDR8:%.+]] = bitcast i8** [[BPADDR8]] to [[TT]]**
+ // CHECK-DAG: [[CPADDR8:%.+]] = bitcast i8** [[PADDR8]] to [[TT]]**
+ // CHECK-DAG: store [[TT]]* %{{.+}}, [[TT]]** [[CBPADDR8]]
+ // CHECK-DAG: store [[TT]]* %{{.+}}, [[TT]]** [[CPADDR8]]
+ // CHECK-DAG: store i[[SZ]] {{12|16}}, i[[SZ]]* [[SADDR8]]
// CHECK: store i32 [[RET]], i32* [[RHV:%.+]], align 4
// CHECK: [[RET2:%.+]] = load i32, i32* [[RHV]], align 4
@@ -468,48 +470,53 @@ int bar(int n){
// CHECK-DAG: [[BPR]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP:%.+]], i32 0, i32 0
// CHECK-DAG: [[PR]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P:%.+]], i32 0, i32 0
// CHECK-DAG: [[SR]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S:%.+]], i32 0, i32 0
-// CHECK-DAG: [[SADDR0:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX0:[0-9]+]]
-// CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX0]]
-// CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX0]]
-// CHECK-DAG: [[SADDR1:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX1:[0-9]+]]
-// CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX1]]
-// CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX1]]
-// CHECK-DAG: [[SADDR2:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX2:[0-9]+]]
-// CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX2]]
-// CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX2]]
-// CHECK-DAG: [[SADDR3:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX3:[0-9]+]]
-// CHECK-DAG: [[BPADDR3:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX3]]
-// CHECK-DAG: [[PADDR3:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX3]]
+// CHECK-DAG: [[SADDR0:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX0:0]]
+// CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 0, i32 [[IDX0]]
+// CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 0, i32 [[IDX0]]
+// CHECK-DAG: [[SADDR1:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX1:1]]
+// CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 0, i32 [[IDX1]]
+// CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 0, i32 [[IDX1]]
+// CHECK-DAG: [[SADDR2:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX2:2]]
+// CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 0, i32 [[IDX2]]
+// CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 0, i32 [[IDX2]]
+// CHECK-DAG: [[SADDR3:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX3:3]]
+// CHECK-DAG: [[BPADDR3:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 0, i32 [[IDX3]]
+// CHECK-DAG: [[PADDR3:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 0, i32 [[IDX3]]
+// CHECK-DAG: [[SADDR4:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX4:4]]
+// CHECK-DAG: [[BPADDR4:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 0, i32 [[IDX4]]
+// CHECK-DAG: [[PADDR4:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 0, i32 [[IDX4]]
// The names below are not necessarily consistent with the names used for the
// addresses above as some are repeated.
-// CHECK-DAG: [[BP0:%[^,]+]] = inttoptr i[[SZ]] [[VLA0]] to i8*
-// CHECK-DAG: [[P0:%[^,]+]] = inttoptr i[[SZ]] [[VLA0]] to i8*
-// CHECK-DAG: store i8* [[BP0]], i8** {{%[^,]+}}
-// CHECK-DAG: store i8* [[P0]], i8** {{%[^,]+}}
-// CHECK-DAG: store i[[SZ]] {{4|8}}, i[[SZ]]* {{%[^,]+}}
-
-// CHECK-DAG: store i8* inttoptr (i[[SZ]] 2 to i8*), i8** {{%[^,]+}}
-// CHECK-DAG: store i8* inttoptr (i[[SZ]] 2 to i8*), i8** {{%[^,]+}}
-// CHECK-DAG: store i[[SZ]] {{4|8}}, i[[SZ]]* {{%[^,]+}}
-
-// CHECK-DAG: [[BP2:%[^,]+]] = inttoptr i[[SZ]] [[B_CVAL]] to i8*
-// CHECK-DAG: [[P2:%[^,]+]] = inttoptr i[[SZ]] [[B_CVAL]] to i8*
-// CHECK-DAG: store i8* [[BP2]], i8** {{%[^,]+}}
-// CHECK-DAG: store i8* [[P2]], i8** {{%[^,]+}}
-// CHECK-DAG: store i[[SZ]] 4, i[[SZ]]* {{%[^,]+}}
-
-// CHECK-DAG: [[BP3:%[^,]+]] = bitcast [[S1]]* %{{.+}} to i8*
-// CHECK-DAG: [[P3:%[^,]+]] = bitcast [[S1]]* %{{.+}} to i8*
-// CHECK-DAG: store i8* [[BP3]], i8** {{%[^,]+}}
-// CHECK-DAG: store i8* [[P3]], i8** {{%[^,]+}}
-// CHECK-DAG: store i[[SZ]] 8, i[[SZ]]* {{%[^,]+}}
-
-// CHECK-DAG: [[BP4:%[^,]+]] = bitcast i16* %{{.+}} to i8*
-// CHECK-DAG: [[P4:%[^,]+]] = bitcast i16* %{{.+}} to i8*
-// CHECK-DAG: store i8* [[BP4]], i8** {{%[^,]+}}
-// CHECK-DAG: store i8* [[P4]], i8** {{%[^,]+}}
-// CHECK-DAG: store i[[SZ]] [[CSIZE]], i[[SZ]]* {{%[^,]+}}
+// CHECK-DAG: [[CBPADDR3:%.+]] = bitcast i8** [[BPADDR3]] to i[[SZ]]*
+// CHECK-DAG: [[CPADDR3:%.+]] = bitcast i8** [[PADDR3]] to i[[SZ]]*
+// CHECK-DAG: store i[[SZ]] [[VLA0]], i[[SZ]]* [[CBPADDR3]]
+// CHECK-DAG: store i[[SZ]] [[VLA0]], i[[SZ]]* [[CPADDR3]]
+// CHECK-DAG: store i[[SZ]] {{4|8}}, i[[SZ]]* [[SADDR3]]
+
+// CHECK-DAG: [[CBPADDR2:%.+]] = bitcast i8** [[BPADDR2]] to i[[SZ]]*
+// CHECK-DAG: [[CPADDR2:%.+]] = bitcast i8** [[PADDR2]] to i[[SZ]]*
+// CHECK-DAG: store i[[SZ]] 2, i[[SZ]]* [[CBPADDR2]]
+// CHECK-DAG: store i[[SZ]] 2, i[[SZ]]* [[CPADDR2]]
+// CHECK-DAG: store i[[SZ]] {{4|8}}, i[[SZ]]* [[SADDR2]]
+
+// CHECK-DAG: [[CBPADDR1:%.+]] = bitcast i8** [[BPADDR1]] to i[[SZ]]*
+// CHECK-DAG: [[CPADDR1:%.+]] = bitcast i8** [[PADDR1]] to i[[SZ]]*
+// CHECK-DAG: store i[[SZ]] [[B_CVAL]], i[[SZ]]* [[CBPADDR1]]
+// CHECK-DAG: store i[[SZ]] [[B_CVAL]], i[[SZ]]* [[CPADDR1]]
+// CHECK-DAG: store i[[SZ]] 4, i[[SZ]]* [[SADDR1]]
+
+// CHECK-DAG: [[CBPADDR0:%.+]] = bitcast i8** [[BPADDR0]] to [[S1]]**
+// CHECK-DAG: [[CPADDR0:%.+]] = bitcast i8** [[PADDR0]] to [[S1]]**
+// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CBPADDR0]]
+// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CPADDR0]]
+// CHECK-DAG: store i[[SZ]] 8, i[[SZ]]* [[SADDR0]]
+
+// CHECK-DAG: [[CBPADDR4:%.+]] = bitcast i8** [[BPADDR4]] to i16**
+// CHECK-DAG: [[CPADDR4:%.+]] = bitcast i8** [[PADDR4]] to i16**
+// CHECK-DAG: store i16* %{{.+}}, i16** [[CBPADDR4]]
+// CHECK-DAG: store i16* %{{.+}}, i16** [[CPADDR4]]
+// CHECK-DAG: store i[[SZ]] [[CSIZE]], i[[SZ]]* [[SADDR4]]
// CHECK: store i32 [[RET]], i32* [[RHV:%.+]], align 4
// CHECK: [[RET2:%.+]] = load i32, i32* [[RHV]], align 4
@@ -533,29 +540,31 @@ int bar(int n){
// CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[BP]], i32 0, i32 0
// CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[P]], i32 0, i32 0
-// CHECK-DAG: store i8* [[BP0:%[^,]+]], i8** [[BPADDR0]]
-// CHECK-DAG: store i8* [[P0:%[^,]+]], i8** [[PADDR0]]
-// CHECK-DAG: [[BP0]] = inttoptr i[[SZ]] [[VAL0:%.+]] to i8*
-// CHECK-DAG: [[P0]] = inttoptr i[[SZ]] [[VAL0]] to i8*
+// CHECK-DAG: [[CBPADDR0:%.+]] = bitcast i8** [[BPADDR0]] to i[[SZ]]*
+// CHECK-DAG: [[CPADDR0:%.+]] = bitcast i8** [[PADDR0]] to i[[SZ]]*
+// CHECK-DAG: store i[[SZ]] [[VAL0:%[^,]+]], i[[SZ]]* [[CBPADDR0]]
+// CHECK-DAG: store i[[SZ]] [[VAL0]], i[[SZ]]* [[CPADDR0]]
// CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[BP]], i32 0, i32 1
// CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[P]], i32 0, i32 1
-// CHECK-DAG: store i8* [[BP1:%[^,]+]], i8** [[BPADDR1]]
-// CHECK-DAG: store i8* [[P1:%[^,]+]], i8** [[PADDR1]]
-// CHECK-DAG: [[BP1]] = inttoptr i[[SZ]] [[VAL1:%.+]] to i8*
-// CHECK-DAG: [[P1]] = inttoptr i[[SZ]] [[VAL1]] to i8*
+// CHECK-DAG: [[CBPADDR1:%.+]] = bitcast i8** [[BPADDR1]] to i[[SZ]]*
+// CHECK-DAG: [[CPADDR1:%.+]] = bitcast i8** [[PADDR1]] to i[[SZ]]*
+// CHECK-DAG: store i[[SZ]] [[VAL1:%[^,]+]], i[[SZ]]* [[CBPADDR1]]
+// CHECK-DAG: store i[[SZ]] [[VAL1]], i[[SZ]]* [[CPADDR1]]
// CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[BP]], i32 0, i32 2
// CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[P]], i32 0, i32 2
-// CHECK-DAG: store i8* [[BP2:%[^,]+]], i8** [[BPADDR2]]
-// CHECK-DAG: store i8* [[P2:%[^,]+]], i8** [[PADDR2]]
+// CHECK-DAG: [[CBPADDR2:%.+]] = bitcast i8** [[BPADDR2]] to i[[SZ]]*
+// CHECK-DAG: [[CPADDR2:%.+]] = bitcast i8** [[PADDR2]] to i[[SZ]]*
+// CHECK-DAG: store i[[SZ]] [[VAL2:%[^,]+]], i[[SZ]]* [[CBPADDR2]]
+// CHECK-DAG: store i[[SZ]] [[VAL2]], i[[SZ]]* [[CPADDR2]]
// CHECK-DAG: [[BPADDR3:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[BP]], i32 0, i32 3
// CHECK-DAG: [[PADDR3:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[P]], i32 0, i32 3
-// CHECK-DAG: store i8* [[BP3:%[^,]+]], i8** [[BPADDR3]]
-// CHECK-DAG: store i8* [[P3:%[^,]+]], i8** [[PADDR3]]
-// CHECK-DAG: [[BP3]] = bitcast [10 x i32]* %{{.+}} to i8*
-// CHECK-DAG: [[P3]] = bitcast [10 x i32]* %{{.+}} to i8*
+// CHECK-DAG: [[CBPADDR3:%.+]] = bitcast i8** [[BPADDR3]] to [10 x i32]**
+// CHECK-DAG: [[CPADDR3:%.+]] = bitcast i8** [[PADDR3]] to [10 x i32]**
+// CHECK-DAG: store [10 x i32]* [[VAL3:%[^,]+]], [10 x i32]** [[CBPADDR3]]
+// CHECK-DAG: store [10 x i32]* [[VAL3]], [10 x i32]** [[CPADDR3]]
// CHECK: store i32 [[RET]], i32* [[RHV:%.+]], align 4
// CHECK-NEXT: br label %[[IFEND:.+]]
@@ -585,24 +594,24 @@ int bar(int n){
// CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* [[BP]], i32 0, i32 0
// CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* [[P]], i32 0, i32 0
-// CHECK-DAG: store i8* [[BP0:%[^,]+]], i8** [[BPADDR0]]
-// CHECK-DAG: store i8* [[P0:%[^,]+]], i8** [[PADDR0]]
-// CHECK-DAG: [[BP0]] = inttoptr i[[SZ]] [[VAL0:%.+]] to i8*
-// CHECK-DAG: [[P0]] = inttoptr i[[SZ]] [[VAL0]] to i8*
+// CHECK-DAG: [[CBPADDR0:%.+]] = bitcast i8** [[BPADDR0]] to i[[SZ]]*
+// CHECK-DAG: [[CPADDR0:%.+]] = bitcast i8** [[PADDR0]] to i[[SZ]]*
+// CHECK-DAG: store i[[SZ]] [[VAL0:%[^,]+]], i[[SZ]]* [[CBPADDR0]]
+// CHECK-DAG: store i[[SZ]] [[VAL0]], i[[SZ]]* [[CPADDR0]]
// CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* [[BP]], i32 0, i32 1
// CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* [[P]], i32 0, i32 1
-// CHECK-DAG: store i8* [[BP1:%[^,]+]], i8** [[BPADDR1]]
-// CHECK-DAG: store i8* [[P1:%[^,]+]], i8** [[PADDR1]]
-// CHECK-DAG: [[BP1]] = inttoptr i[[SZ]] [[VAL1:%.+]] to i8*
-// CHECK-DAG: [[P1]] = inttoptr i[[SZ]] [[VAL1]] to i8*
+// CHECK-DAG: [[CBPADDR1:%.+]] = bitcast i8** [[BPADDR1]] to i[[SZ]]*
+// CHECK-DAG: [[CPADDR1:%.+]] = bitcast i8** [[PADDR1]] to i[[SZ]]*
+// CHECK-DAG: store i[[SZ]] [[VAL1:%[^,]+]], i[[SZ]]* [[CBPADDR1]]
+// CHECK-DAG: store i[[SZ]] [[VAL1]], i[[SZ]]* [[CPADDR1]]
// CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* [[BP]], i32 0, i32 2
// CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* [[P]], i32 0, i32 2
-// CHECK-DAG: store i8* [[BP2:%[^,]+]], i8** [[BPADDR2]]
-// CHECK-DAG: store i8* [[P2:%[^,]+]], i8** [[PADDR2]]
-// CHECK-DAG: [[BP2]] = bitcast [10 x i32]* %{{.+}} to i8*
-// CHECK-DAG: [[P2]] = bitcast [10 x i32]* %{{.+}} to i8*
+// CHECK-DAG: [[CBPADDR2:%.+]] = bitcast i8** [[BPADDR2]] to [10 x i32]**
+// CHECK-DAG: [[CPADDR2:%.+]] = bitcast i8** [[PADDR2]] to [10 x i32]**
+// CHECK-DAG: store [10 x i32]* [[VAL2:%[^,]+]], [10 x i32]** [[CBPADDR2]]
+// CHECK-DAG: store [10 x i32]* [[VAL2]], [10 x i32]** [[CPADDR2]]
// CHECK: store i32 [[RET]], i32* [[RHV:%.+]], align 4
// CHECK-NEXT: br label %[[IFEND:.+]]
diff --git a/test/OpenMP/target_codegen_global_capture.cpp b/test/OpenMP/target_codegen_global_capture.cpp
index b08bf10f9f29..eb34082b2940 100644
--- a/test/OpenMP/target_codegen_global_capture.cpp
+++ b/test/OpenMP/target_codegen_global_capture.cpp
@@ -36,10 +36,10 @@ double Gd = 4.0;
// CHECK-SAME: i16 {{[^,]*}}[[B:%[^,]+]],
// CHECK-SAME: i16 {{[^,]*}}[[C:%[^,]+]],
// CHECK-SAME: i16 {{[^,]*}}[[D:%[^,]+]])
-// CHECK: [[LA:%.+]] = alloca i16
-// CHECK: [[LB:%.+]] = alloca i16
-// CHECK: [[LC:%.+]] = alloca i16
-// CHECK: [[LD:%.+]] = alloca i16
+// CHECK: [[LA:%.+]] = alloca i16,
+// CHECK: [[LB:%.+]] = alloca i16,
+// CHECK: [[LC:%.+]] = alloca i16,
+// CHECK: [[LD:%.+]] = alloca i16,
int foo(short a, short b, short c, short d){
static float Sa = 5.0;
static float Sb = 6.0;
@@ -61,22 +61,22 @@ int foo(short a, short b, short c, short d){
// CHECK-DAG: store i16 [[VALLB]], i16* [[CONVLB:%.+]],
// CHECK-DAG: [[CONVLB]] = bitcast i[[sz:64|32]]* [[CADDRLB:%.+]] to i16*
// CHECK-DAG: [[CVALLB:%.+]] = load i[[sz]], i[[sz]]* [[CADDRLB]],
- // CHECK-DAG: [[CPTRLB:%.+]] = inttoptr i[[sz]] [[CVALLB]] to i8*
- // CHECK-DAG: store i8* [[CPTRLB]], i8** [[GEPLB:%.+]],
+ // CHECK-DAG: store i[[sz]] [[CVALLB]], i[[sz]]* [[CBP:%.+]],
+ // CHECK-DAG: [[CBP]] = bitcast i8** [[GEPLB:%.+]] to i[[sz]]*
// CHECK-DAG: [[GEPLB]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}}
// CHECK-DAG: store i16 [[VALLC]], i16* [[CONVLC:%.+]],
// CHECK-DAG: [[CONVLC]] = bitcast i[[sz]]* [[CADDRLC:%.+]] to i16*
// CHECK-DAG: [[CVALLC:%.+]] = load i[[sz]], i[[sz]]* [[CADDRLC]],
- // CHECK-DAG: [[CPTRLC:%.+]] = inttoptr i[[sz]] [[CVALLC]] to i8*
- // CHECK-DAG: store i8* [[CPTRLC]], i8** [[GEPLC:%.+]],
+ // CHECK-DAG: store i[[sz]] [[CVALLC]], i[[sz]]* [[CBP:%.+]],
+ // CHECK-DAG: [[CBP]] = bitcast i8** [[GEPLC:%.+]] to i[[sz]]*
// CHECK-DAG: [[GEPLC]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}}
// CHECK-DAG: store i16 [[VALLD]], i16* [[CONVLD:%.+]],
// CHECK-DAG: [[CONVLD]] = bitcast i[[sz]]* [[CADDRLD:%.+]] to i16*
// CHECK-DAG: [[CVALLD:%.+]] = load i[[sz]], i[[sz]]* [[CADDRLD]],
- // CHECK-DAG: [[CPTRLD:%.+]] = inttoptr i[[sz]] [[CVALLD]] to i8*
- // CHECK-DAG: store i8* [[CPTRLD]], i8** [[GEPLD:%.+]],
+ // CHECK-DAG: store i[[sz]] [[CVALLD]], i[[sz]]* [[CBP:%.+]],
+ // CHECK-DAG: [[CBP]] = bitcast i8** [[GEPLD:%.+]] to i[[sz]]*
// CHECK-DAG: [[GEPLD]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}}
// 3 static vars being captured.
@@ -84,22 +84,22 @@ int foo(short a, short b, short c, short d){
// CHECK-DAG: store float [[VALFB]], float* [[CONVFB:%.+]],
// CHECK-DAG: [[CONVFB]] = bitcast i[[sz]]* [[CADDRFB:%.+]] to float*
// CHECK-DAG: [[CVALFB:%.+]] = load i[[sz]], i[[sz]]* [[CADDRFB]],
- // CHECK-DAG: [[CPTRFB:%.+]] = inttoptr i[[sz]] [[CVALFB]] to i8*
- // CHECK-DAG: store i8* [[CPTRFB]], i8** [[GEPFB:%.+]],
+ // CHECK-DAG: store i[[sz]] [[CVALFB]], i[[sz]]* [[CBP:%.+]],
+ // CHECK-DAG: [[CBP]] = bitcast i8** [[GEPFB:%.+]] to i[[sz]]*
// CHECK-DAG: [[GEPFB]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}}
// CHECK-DAG: store float [[VALFC]], float* [[CONVFC:%.+]],
// CHECK-DAG: [[CONVFC]] = bitcast i[[sz]]* [[CADDRFC:%.+]] to float*
// CHECK-DAG: [[CVALFC:%.+]] = load i[[sz]], i[[sz]]* [[CADDRFC]],
- // CHECK-DAG: [[CPTRFC:%.+]] = inttoptr i[[sz]] [[CVALFC]] to i8*
- // CHECK-DAG: store i8* [[CPTRFC]], i8** [[GEPFC:%.+]],
+ // CHECK-DAG: store i[[sz]] [[CVALFC]], i[[sz]]* [[CBP:%.+]],
+ // CHECK-DAG: [[CBP]] = bitcast i8** [[GEPFC:%.+]] to i[[sz]]*
// CHECK-DAG: [[GEPFC]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}}
// CHECK-DAG: store float [[VALFD]], float* [[CONVFD:%.+]],
// CHECK-DAG: [[CONVFD]] = bitcast i[[sz]]* [[CADDRFD:%.+]] to float*
// CHECK-DAG: [[CVALFD:%.+]] = load i[[sz]], i[[sz]]* [[CADDRFD]],
- // CHECK-DAG: [[CPTRFD:%.+]] = inttoptr i[[sz]] [[CVALFD]] to i8*
- // CHECK-DAG: store i8* [[CPTRFD]], i8** [[GEPFD:%.+]],
+ // CHECK-DAG: store i[[sz]] [[CVALFD]], i[[sz]]* [[CBP:%.+]],
+ // CHECK-DAG: [[CBP]] = bitcast i8** [[GEPFD:%.+]] to i[[sz]]*
// CHECK-DAG: [[GEPFD]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}}
// 3 static global vars being captured.
@@ -107,25 +107,28 @@ int foo(short a, short b, short c, short d){
// CHECK-64-DAG: store double [[VALGB]], double* [[CONVGB:%.+]],
// CHECK-64-DAG: [[CONVGB]] = bitcast i[[sz]]* [[CADDRGB:%.+]] to double*
// CHECK-64-DAG: [[CVALGB:%.+]] = load i[[sz]], i[[sz]]* [[CADDRGB]],
- // CHECK-64-DAG: [[CPTRGB:%.+]] = inttoptr i[[sz]] [[CVALGB]] to i8*
- // CHECK-64-DAG: store i8* [[CPTRGB]], i8** [[GEPGB:%.+]],
- // CHECK-32-DAG: store i8* bitcast (double* @Gb to i8*), i8** [[GEPGB:%.+]],
+ // CHECK-64-DAG: store i[[sz]] [[CVALGB]], i[[sz]]* [[CBP:%.+]],
+ // CHECK-64-DAG: [[CBP]] = bitcast i8** [[GEPGB:%.+]] to i[[sz]]*
+ // CHECK-32-DAG: store double* @Gb, double** [[CBP:%.+]],
+ // CHECK-32-DAG: [[CBP]] = bitcast i8** [[GEPGB:%.+]] to double**
// CHECK-DAG: [[GEPGB]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}}
// CHECK-64-DAG: store double [[VALGC]], double* [[CONVGC:%.+]],
// CHECK-64-DAG: [[CONVGC]] = bitcast i[[sz]]* [[CADDRGC:%.+]] to double*
// CHECK-64-DAG: [[CVALGC:%.+]] = load i[[sz]], i[[sz]]* [[CADDRGC]],
- // CHECK-64-DAG: [[CPTRGC:%.+]] = inttoptr i[[sz]] [[CVALGC]] to i8*
- // CHECK-64-DAG: store i8* [[CPTRGC]], i8** [[GEPGC:%.+]],
- // CHECK-32-DAG: store i8* bitcast (double* @Gc to i8*), i8** [[GEPGC:%.+]],
+ // CHECK-64-DAG: store i[[sz]] [[CVALGC]], i[[sz]]* [[CBP:%.+]],
+ // CHECK-64-DAG: [[CBP]] = bitcast i8** [[GEPGC:%.+]] to i[[sz]]*
+ // CHECK-32-DAG: store double* @Gc, double** [[CBP:%.+]],
+ // CHECK-32-DAG: [[CBP]] = bitcast i8** [[GEPGC:%.+]] to double**
// CHECK-DAG: [[GEPGC]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}}
// CHECK-64-DAG: store double [[VALGD]], double* [[CONVGD:%.+]],
// CHECK-64-DAG: [[CONVGD]] = bitcast i[[sz]]* [[CADDRGD:%.+]] to double*
// CHECK-64-DAG: [[CVALGD:%.+]] = load i[[sz]], i[[sz]]* [[CADDRGD]],
- // CHECK-64-DAG: [[CPTRGD:%.+]] = inttoptr i[[sz]] [[CVALGD]] to i8*
- // CHECK-64-DAG: store i8* [[CPTRGD]], i8** [[GEPGD:%.+]],
- // CHECK-32-DAG: store i8* bitcast (double* @Gd to i8*), i8** [[GEPGD:%.+]],
+ // CHECK-64-DAG: store i[[sz]] [[CVALGD]], i[[sz]]* [[CBP:%.+]],
+ // CHECK-64-DAG: [[CBP]] = bitcast i8** [[GEPGD:%.+]] to i[[sz]]*
+ // CHECK-32-DAG: store double* @Gd, double** [[CBP:%.+]],
+ // CHECK-32-DAG: [[CBP]] = bitcast i8** [[GEPGD:%.+]] to double**
// CHECK-DAG: [[GEPGD]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}}
// CHECK: call i32 @__tgt_target
@@ -197,22 +200,22 @@ int bar(short a, short b, short c, short d){
// CHECK-DAG: store i16 [[VALLB]], i16* [[CONVLB:%.+]],
// CHECK-DAG: [[CONVLB]] = bitcast i[[sz:64|32]]* [[CADDRLB:%.+]] to i16*
// CHECK-DAG: [[CVALLB:%.+]] = load i[[sz]], i[[sz]]* [[CADDRLB]],
- // CHECK-DAG: [[CPTRLB:%.+]] = inttoptr i[[sz]] [[CVALLB]] to i8*
- // CHECK-DAG: store i8* [[CPTRLB]], i8** [[GEPLB:%.+]],
+ // CHECK-DAG: store i[[sz]] [[CVALLB]], i[[sz]]* [[CBP:%.+]],
+ // CHECK-DAG: [[CBP]] = bitcast i8** [[GEPLB:%.+]] to i[[sz]]*
// CHECK-DAG: [[GEPLB]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}}
// CHECK-DAG: store i16 [[VALLC]], i16* [[CONVLC:%.+]],
// CHECK-DAG: [[CONVLC]] = bitcast i[[sz]]* [[CADDRLC:%.+]] to i16*
// CHECK-DAG: [[CVALLC:%.+]] = load i[[sz]], i[[sz]]* [[CADDRLC]],
- // CHECK-DAG: [[CPTRLC:%.+]] = inttoptr i[[sz]] [[CVALLC]] to i8*
- // CHECK-DAG: store i8* [[CPTRLC]], i8** [[GEPLC:%.+]],
+ // CHECK-DAG: store i[[sz]] [[CVALLC]], i[[sz]]* [[CBP:%.+]],
+ // CHECK-DAG: [[CBP]] = bitcast i8** [[GEPLC:%.+]] to i[[sz]]*
// CHECK-DAG: [[GEPLC]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}}
// CHECK-DAG: store i16 [[VALLD]], i16* [[CONVLD:%.+]],
// CHECK-DAG: [[CONVLD]] = bitcast i[[sz]]* [[CADDRLD:%.+]] to i16*
// CHECK-DAG: [[CVALLD:%.+]] = load i[[sz]], i[[sz]]* [[CADDRLD]],
- // CHECK-DAG: [[CPTRLD:%.+]] = inttoptr i[[sz]] [[CVALLD]] to i8*
- // CHECK-DAG: store i8* [[CPTRLD]], i8** [[GEPLD:%.+]],
+ // CHECK-DAG: store i[[sz]] [[CVALLD]], i[[sz]]* [[CBP:%.+]],
+ // CHECK-DAG: [[CBP]] = bitcast i8** [[GEPLD:%.+]] to i[[sz]]*
// CHECK-DAG: [[GEPLD]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}}
// 3 static vars being captured.
@@ -220,22 +223,22 @@ int bar(short a, short b, short c, short d){
// CHECK-DAG: store float [[VALFB]], float* [[CONVFB:%.+]],
// CHECK-DAG: [[CONVFB]] = bitcast i[[sz]]* [[CADDRFB:%.+]] to float*
// CHECK-DAG: [[CVALFB:%.+]] = load i[[sz]], i[[sz]]* [[CADDRFB]],
- // CHECK-DAG: [[CPTRFB:%.+]] = inttoptr i[[sz]] [[CVALFB]] to i8*
- // CHECK-DAG: store i8* [[CPTRFB]], i8** [[GEPFB:%.+]],
+ // CHECK-DAG: store i[[sz]] [[CVALFB]], i[[sz]]* [[CBP:%.+]],
+ // CHECK-DAG: [[CBP]] = bitcast i8** [[GEPFB:%.+]] to i[[sz]]*
// CHECK-DAG: [[GEPFB]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}}
// CHECK-DAG: store float [[VALFC]], float* [[CONVFC:%.+]],
// CHECK-DAG: [[CONVFC]] = bitcast i[[sz]]* [[CADDRFC:%.+]] to float*
// CHECK-DAG: [[CVALFC:%.+]] = load i[[sz]], i[[sz]]* [[CADDRFC]],
- // CHECK-DAG: [[CPTRFC:%.+]] = inttoptr i[[sz]] [[CVALFC]] to i8*
- // CHECK-DAG: store i8* [[CPTRFC]], i8** [[GEPFC:%.+]],
+ // CHECK-DAG: store i[[sz]] [[CVALFC]], i[[sz]]* [[CBP:%.+]],
+ // CHECK-DAG: [[CBP]] = bitcast i8** [[GEPFC:%.+]] to i[[sz]]*
// CHECK-DAG: [[GEPFC]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}}
// CHECK-DAG: store float [[VALFD]], float* [[CONVFD:%.+]],
// CHECK-DAG: [[CONVFD]] = bitcast i[[sz]]* [[CADDRFD:%.+]] to float*
// CHECK-DAG: [[CVALFD:%.+]] = load i[[sz]], i[[sz]]* [[CADDRFD]],
- // CHECK-DAG: [[CPTRFD:%.+]] = inttoptr i[[sz]] [[CVALFD]] to i8*
- // CHECK-DAG: store i8* [[CPTRFD]], i8** [[GEPFD:%.+]],
+ // CHECK-DAG: store i[[sz]] [[CVALFD]], i[[sz]]* [[CBP:%.+]],
+ // CHECK-DAG: [[CBP]] = bitcast i8** [[GEPFD:%.+]] to i[[sz]]*
// CHECK-DAG: [[GEPFD]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}}
// 3 static global vars being captured.
@@ -243,25 +246,28 @@ int bar(short a, short b, short c, short d){
// CHECK-64-DAG: store double [[VALGB]], double* [[CONVGB:%.+]],
// CHECK-64-DAG: [[CONVGB]] = bitcast i[[sz]]* [[CADDRGB:%.+]] to double*
// CHECK-64-DAG: [[CVALGB:%.+]] = load i[[sz]], i[[sz]]* [[CADDRGB]],
- // CHECK-64-DAG: [[CPTRGB:%.+]] = inttoptr i[[sz]] [[CVALGB]] to i8*
- // CHECK-64-DAG: store i8* [[CPTRGB]], i8** [[GEPGB:%.+]],
- // CHECK-32-DAG: store i8* bitcast (double* @Gb to i8*), i8** [[GEPGB:%.+]],
+ // CHECK-64-DAG: store i[[sz]] [[CVALGB]], i[[sz]]* [[CBP:%.+]],
+ // CHECK-64-DAG: [[CBP]] = bitcast i8** [[GEPGB:%.+]] to i[[sz]]*
+ // CHECK-32-DAG: store double* @Gb, double** [[CBP:%.+]],
+ // CHECK-32-DAG: [[CBP]] = bitcast i8** [[GEPGB:%.+]] to double**
// CHECK-DAG: [[GEPGB]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}}
// CHECK-64-DAG: store double [[VALGC]], double* [[CONVGC:%.+]],
// CHECK-64-DAG: [[CONVGC]] = bitcast i[[sz]]* [[CADDRGC:%.+]] to double*
// CHECK-64-DAG: [[CVALGC:%.+]] = load i[[sz]], i[[sz]]* [[CADDRGC]],
- // CHECK-64-DAG: [[CPTRGC:%.+]] = inttoptr i[[sz]] [[CVALGC]] to i8*
- // CHECK-64-DAG: store i8* [[CPTRGC]], i8** [[GEPGC:%.+]],
- // CHECK-32-DAG: store i8* bitcast (double* @Gc to i8*), i8** [[GEPGC:%.+]],
+ // CHECK-64-DAG: store i[[sz]] [[CVALGC]], i[[sz]]* [[CBP:%.+]],
+ // CHECK-64-DAG: [[CBP]] = bitcast i8** [[GEPGC:%.+]] to i[[sz]]*
+ // CHECK-32-DAG: store double* @Gc, double** [[CBP:%.+]],
+ // CHECK-32-DAG: [[CBP]] = bitcast i8** [[GEPGC:%.+]] to double**
// CHECK-DAG: [[GEPGC]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}}
// CHECK-64-DAG: store double [[VALGD]], double* [[CONVGD:%.+]],
// CHECK-64-DAG: [[CONVGD]] = bitcast i[[sz]]* [[CADDRGD:%.+]] to double*
// CHECK-64-DAG: [[CVALGD:%.+]] = load i[[sz]], i[[sz]]* [[CADDRGD]],
- // CHECK-64-DAG: [[CPTRGD:%.+]] = inttoptr i[[sz]] [[CVALGD]] to i8*
- // CHECK-64-DAG: store i8* [[CPTRGD]], i8** [[GEPGD:%.+]],
- // CHECK-32-DAG: store i8* bitcast (double* @Gd to i8*), i8** [[GEPGD:%.+]],
+ // CHECK-64-DAG: store i[[sz]] [[CVALGD]], i[[sz]]* [[CBP:%.+]],
+ // CHECK-64-DAG: [[CBP]] = bitcast i8** [[GEPGD:%.+]] to i[[sz]]*
+ // CHECK-32-DAG: store double* @Gd, double** [[CBP:%.+]],
+ // CHECK-32-DAG: [[CBP]] = bitcast i8** [[GEPGD:%.+]] to double**
// CHECK-DAG: [[GEPGD]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}}
// CHECK: call i32 @__tgt_target
@@ -339,22 +345,22 @@ int tbar(T a, T b, T c, T d){
// CHECK-DAG: store i16 [[VALLB]], i16* [[CONVLB:%.+]],
// CHECK-DAG: [[CONVLB]] = bitcast i[[sz:64|32]]* [[CADDRLB:%.+]] to i16*
// CHECK-DAG: [[CVALLB:%.+]] = load i[[sz]], i[[sz]]* [[CADDRLB]],
- // CHECK-DAG: [[CPTRLB:%.+]] = inttoptr i[[sz]] [[CVALLB]] to i8*
- // CHECK-DAG: store i8* [[CPTRLB]], i8** [[GEPLB:%.+]],
+ // CHECK-DAG: store i[[sz]] [[CVALLB]], i[[sz]]* [[CBP:%.+]],
+ // CHECK-DAG: [[CBP]] = bitcast i8** [[GEPLB:%.+]] to i[[sz]]*
// CHECK-DAG: [[GEPLB]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}}
// CHECK-DAG: store i16 [[VALLC]], i16* [[CONVLC:%.+]],
// CHECK-DAG: [[CONVLC]] = bitcast i[[sz]]* [[CADDRLC:%.+]] to i16*
// CHECK-DAG: [[CVALLC:%.+]] = load i[[sz]], i[[sz]]* [[CADDRLC]],
- // CHECK-DAG: [[CPTRLC:%.+]] = inttoptr i[[sz]] [[CVALLC]] to i8*
- // CHECK-DAG: store i8* [[CPTRLC]], i8** [[GEPLC:%.+]],
+ // CHECK-DAG: store i[[sz]] [[CVALLC]], i[[sz]]* [[CBP:%.+]],
+ // CHECK-DAG: [[CBP]] = bitcast i8** [[GEPLC:%.+]] to i[[sz]]*
// CHECK-DAG: [[GEPLC]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}}
// CHECK-DAG: store i16 [[VALLD]], i16* [[CONVLD:%.+]],
// CHECK-DAG: [[CONVLD]] = bitcast i[[sz]]* [[CADDRLD:%.+]] to i16*
// CHECK-DAG: [[CVALLD:%.+]] = load i[[sz]], i[[sz]]* [[CADDRLD]],
- // CHECK-DAG: [[CPTRLD:%.+]] = inttoptr i[[sz]] [[CVALLD]] to i8*
- // CHECK-DAG: store i8* [[CPTRLD]], i8** [[GEPLD:%.+]],
+ // CHECK-DAG: store i[[sz]] [[CVALLD]], i[[sz]]* [[CBP:%.+]],
+ // CHECK-DAG: [[CBP]] = bitcast i8** [[GEPLD:%.+]] to i[[sz]]*
// CHECK-DAG: [[GEPLD]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}}
// 3 static vars being captured.
@@ -362,22 +368,22 @@ int tbar(T a, T b, T c, T d){
// CHECK-DAG: store float [[VALFB]], float* [[CONVFB:%.+]],
// CHECK-DAG: [[CONVFB]] = bitcast i[[sz]]* [[CADDRFB:%.+]] to float*
// CHECK-DAG: [[CVALFB:%.+]] = load i[[sz]], i[[sz]]* [[CADDRFB]],
- // CHECK-DAG: [[CPTRFB:%.+]] = inttoptr i[[sz]] [[CVALFB]] to i8*
- // CHECK-DAG: store i8* [[CPTRFB]], i8** [[GEPFB:%.+]],
+ // CHECK-DAG: store i[[sz]] [[CVALFB]], i[[sz]]* [[CBP:%.+]],
+ // CHECK-DAG: [[CBP]] = bitcast i8** [[GEPFB:%.+]] to i[[sz]]*
// CHECK-DAG: [[GEPFB]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}}
// CHECK-DAG: store float [[VALFC]], float* [[CONVFC:%.+]],
// CHECK-DAG: [[CONVFC]] = bitcast i[[sz]]* [[CADDRFC:%.+]] to float*
// CHECK-DAG: [[CVALFC:%.+]] = load i[[sz]], i[[sz]]* [[CADDRFC]],
- // CHECK-DAG: [[CPTRFC:%.+]] = inttoptr i[[sz]] [[CVALFC]] to i8*
- // CHECK-DAG: store i8* [[CPTRFC]], i8** [[GEPFC:%.+]],
+ // CHECK-DAG: store i[[sz]] [[CVALFC]], i[[sz]]* [[CBP:%.+]],
+ // CHECK-DAG: [[CBP]] = bitcast i8** [[GEPFC:%.+]] to i[[sz]]*
// CHECK-DAG: [[GEPFC]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}}
// CHECK-DAG: store float [[VALFD]], float* [[CONVFD:%.+]],
// CHECK-DAG: [[CONVFD]] = bitcast i[[sz]]* [[CADDRFD:%.+]] to float*
// CHECK-DAG: [[CVALFD:%.+]] = load i[[sz]], i[[sz]]* [[CADDRFD]],
- // CHECK-DAG: [[CPTRFD:%.+]] = inttoptr i[[sz]] [[CVALFD]] to i8*
- // CHECK-DAG: store i8* [[CPTRFD]], i8** [[GEPFD:%.+]],
+ // CHECK-DAG: store i[[sz]] [[CVALFD]], i[[sz]]* [[CBP:%.+]],
+ // CHECK-DAG: [[CBP]] = bitcast i8** [[GEPFD:%.+]] to i[[sz]]*
// CHECK-DAG: [[GEPFD]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}}
// 3 static global vars being captured.
@@ -385,25 +391,28 @@ int tbar(T a, T b, T c, T d){
// CHECK-64-DAG: store double [[VALGB]], double* [[CONVGB:%.+]],
// CHECK-64-DAG: [[CONVGB]] = bitcast i[[sz]]* [[CADDRGB:%.+]] to double*
// CHECK-64-DAG: [[CVALGB:%.+]] = load i[[sz]], i[[sz]]* [[CADDRGB]],
- // CHECK-64-DAG: [[CPTRGB:%.+]] = inttoptr i[[sz]] [[CVALGB]] to i8*
- // CHECK-64-DAG: store i8* [[CPTRGB]], i8** [[GEPGB:%.+]],
- // CHECK-32-DAG: store i8* bitcast (double* @Gb to i8*), i8** [[GEPGB:%.+]],
+ // CHECK-64-DAG: store i[[sz]] [[CVALGB]], i[[sz]]* [[CBP:%.+]],
+ // CHECK-64-DAG: [[CBP]] = bitcast i8** [[GEPGB:%.+]] to i[[sz]]*
+ // CHECK-32-DAG: store double* @Gb, double** [[CBP:%.+]],
+ // CHECK-32-DAG: [[CBP]] = bitcast i8** [[GEPGB:%.+]] to double**
// CHECK-DAG: [[GEPGB]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}}
// CHECK-64-DAG: store double [[VALGC]], double* [[CONVGC:%.+]],
// CHECK-64-DAG: [[CONVGC]] = bitcast i[[sz]]* [[CADDRGC:%.+]] to double*
// CHECK-64-DAG: [[CVALGC:%.+]] = load i[[sz]], i[[sz]]* [[CADDRGC]],
- // CHECK-64-DAG: [[CPTRGC:%.+]] = inttoptr i[[sz]] [[CVALGC]] to i8*
- // CHECK-64-DAG: store i8* [[CPTRGC]], i8** [[GEPGC:%.+]],
- // CHECK-32-DAG: store i8* bitcast (double* @Gc to i8*), i8** [[GEPGC:%.+]],
+ // CHECK-64-DAG: store i[[sz]] [[CVALGC]], i[[sz]]* [[CBP:%.+]],
+ // CHECK-64-DAG: [[CBP]] = bitcast i8** [[GEPGC:%.+]] to i[[sz]]*
+ // CHECK-32-DAG: store double* @Gc, double** [[CBP:%.+]],
+ // CHECK-32-DAG: [[CBP]] = bitcast i8** [[GEPGC:%.+]] to double**
// CHECK-DAG: [[GEPGC]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}}
// CHECK-64-DAG: store double [[VALGD]], double* [[CONVGD:%.+]],
// CHECK-64-DAG: [[CONVGD]] = bitcast i[[sz]]* [[CADDRGD:%.+]] to double*
// CHECK-64-DAG: [[CVALGD:%.+]] = load i[[sz]], i[[sz]]* [[CADDRGD]],
- // CHECK-64-DAG: [[CPTRGD:%.+]] = inttoptr i[[sz]] [[CVALGD]] to i8*
- // CHECK-64-DAG: store i8* [[CPTRGD]], i8** [[GEPGD:%.+]],
- // CHECK-32-DAG: store i8* bitcast (double* @Gd to i8*), i8** [[GEPGD:%.+]],
+ // CHECK-64-DAG: store i[[sz]] [[CVALGD]], i[[sz]]* [[CBP:%.+]],
+ // CHECK-64-DAG: [[CBP]] = bitcast i8** [[GEPGD:%.+]] to i[[sz]]*
+ // CHECK-32-DAG: store double* @Gd, double** [[CBP:%.+]],
+ // CHECK-32-DAG: [[CBP]] = bitcast i8** [[GEPGD:%.+]] to double**
// CHECK-DAG: [[GEPGD]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}}
// CHECK: call i32 @__tgt_target
diff --git a/test/OpenMP/target_data_codegen.cpp b/test/OpenMP/target_data_codegen.cpp
index a149ba9332b9..7e5e267d13b6 100644
--- a/test/OpenMP/target_data_codegen.cpp
+++ b/test/OpenMP/target_data_codegen.cpp
@@ -45,8 +45,10 @@ void foo(int arg) {
// CK1-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
// CK1-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
- // CK1-DAG: store i8* bitcast ([100 x double]* @gc to i8*), i8** [[BP0]]
- // CK1-DAG: store i8* bitcast ([100 x double]* @gc to i8*), i8** [[P0]]
+ // CK1-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [100 x double]**
+ // CK1-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [100 x double]**
+ // CK1-DAG: store [100 x double]* @gc, [100 x double]** [[CBP0]]
+ // CK1-DAG: store [100 x double]* @gc, [100 x double]** [[CP0]]
// CK1: %{{.+}} = add nsw i32 %{{[^,]+}}, 1
@@ -71,10 +73,10 @@ void foo(int arg) {
// CK1-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
// CK1-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
- // CK1-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]]
- // CK1-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]]
- // CK1-DAG: [[CBPVAL0]] = bitcast i32* [[VAR0:%.+]] to i8*
- // CK1-DAG: [[CPVAL0]] = bitcast i32* [[VAR0]] to i8*
+ // CK1-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i32**
+ // CK1-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32**
+ // CK1-DAG: store i32* [[VAR0:%.+]], i32** [[CBP0]]
+ // CK1-DAG: store i32* [[VAR0]], i32** [[CP0]]
// CK1: br label %[[IFEND:[^,]+]]
// CK1: [[IFELSE]]
@@ -103,11 +105,11 @@ void foo(int arg) {
// CK1-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
// CK1-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
// CK1-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0
- // CK1-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]]
- // CK1-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]]
+ // CK1-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to float**
+ // CK1-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to float**
+ // CK1-DAG: store float* [[VAR0:%.+]], float** [[CBP0]]
+ // CK1-DAG: store float* [[VAR0]], float** [[CP0]]
// CK1-DAG: store i[[sz]] [[CSVAL0:%[^,]+]], i[[sz]]* [[S0]]
- // CK1-DAG: [[CBPVAL0]] = bitcast float* [[VAR0:%.+]] to i8*
- // CK1-DAG: [[CPVAL0]] = bitcast float* [[VAR0]] to i8*
// CK1-DAG: [[CSVAL0]] = mul nuw i[[sz]] %{{[^,]+}}, 4
// CK1: %{{.+}} = add nsw i32 %{{[^,]+}}, 1
@@ -128,15 +130,18 @@ void foo(int arg) {
// CK1-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
// CK1-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
- // CK1-DAG: store i8* bitcast ([[ST]]* @gb to i8*), i8** [[BP0]]
- // CK1-DAG: store i8* bitcast (double** getelementptr inbounds ([[ST]], [[ST]]* @gb, i32 0, i32 1) to i8*), i8** [[P0]]
+ // CK1-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]**
+ // CK1-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to double***
+ // CK1-DAG: store [[ST]]* @gb, [[ST]]** [[CBP0]]
+ // CK1-DAG: store double** getelementptr inbounds ([[ST]], [[ST]]* @gb, i32 0, i32 1), double*** [[CP0]]
// CK1-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
// CK1-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
- // CK1-DAG: store i8* bitcast (double** getelementptr inbounds ([[ST]], [[ST]]* @gb, i32 0, i32 1) to i8*), i8** [[BP1]]
- // CK1-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]]
- // CK1-DAG: [[CPVAL1]] = bitcast double* [[SEC1:%.+]] to i8*
+ // CK1-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to double***
+ // CK1-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to double**
+ // CK1-DAG: store double** getelementptr inbounds ([[ST]], [[ST]]* @gb, i32 0, i32 1), double*** [[CBP1]]
+ // CK1-DAG: store double* [[SEC1:%.+]], double** [[CP1]]
// CK1-DAG: [[SEC1]] = getelementptr inbounds {{.+}}double* [[SEC11:%[^,]+]], i{{.+}} 0
// CK1-DAG: [[SEC11]] = load double*, double** getelementptr inbounds ([[ST]], [[ST]]* @gb, i32 0, i32 1),
@@ -191,19 +196,19 @@ int bar(int arg){
// CK2-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
// CK2-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
-// CK2-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]]
-// CK2-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]]
-// CK2-DAG: [[CBPVAL0]] = bitcast [[ST]]* [[VAR0:%.+]] to i8*
-// CK2-DAG: [[CPVAL0]] = bitcast double** [[SEC0:%[^,]+]] to i8*
+// CK2-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]**
+// CK2-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to double***
+// CK2-DAG: store [[ST]]* [[VAR0:%.+]], [[ST]]** [[CBP0]]
+// CK2-DAG: store double** [[SEC0:%.+]], double*** [[CP0]]
// CK2-DAG: [[SEC0]] = getelementptr inbounds {{.*}}[[ST]]* [[VAR0]], i32 0, i32 1
// CK2-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
// CK2-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
-// CK2-DAG: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]]
-// CK2-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]]
-// CK2-DAG: [[CBPVAL1]] = bitcast double** [[SEC0]] to i8*
-// CK2-DAG: [[CPVAL1]] = bitcast double* [[SEC1:%[^,]+]] to i8*
+// CK2-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to double***
+// CK2-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to double**
+// CK2-DAG: store double** [[SEC0]], double*** [[CBP1]]
+// CK2-DAG: store double* [[SEC1:%.+]], double** [[CP1]]
// CK2-DAG: [[SEC1]] = getelementptr inbounds {{.*}}double* [[SEC11:%[^,]+]], i{{.+}} 1
// CK2-DAG: [[SEC11]] = load double*, double** [[SEC111:%[^,]+]],
// CK2-DAG: [[SEC111]] = getelementptr inbounds {{.*}}[[ST]]* [[VAR0]], i32 0, i32 1
diff --git a/test/OpenMP/target_data_use_device_ptr_codegen.cpp b/test/OpenMP/target_data_use_device_ptr_codegen.cpp
index c4b389a4cbb8..5e275565170e 100644
--- a/test/OpenMP/target_data_use_device_ptr_codegen.cpp
+++ b/test/OpenMP/target_data_use_device_ptr_codegen.cpp
@@ -33,12 +33,11 @@ void foo(float *&lr, T *&tr) {
float *l;
T *t;
- // CK1-DAG: [[RVAL:%.+]] = bitcast double* [[T:%.+]] to i8*
- // CK1-DAG: [[T]] = load double*, double** [[DECL:@g]],
+ // CK1: [[T:%.+]] = load double*, double** [[DECL:@g]],
// CK1: [[BP:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* %{{.+}}, i32 0, i32 0
- // CK1: store i8* [[RVAL]], i8** [[BP]],
- // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE00]]
// CK1: [[CBP:%.+]] = bitcast i8** [[BP]] to double**
+ // CK1: store double* [[T]], double** [[CBP]],
+ // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE00]]
// CK1: [[VAL:%.+]] = load double*, double** [[CBP]],
// CK1-NOT: store double* [[VAL]], double** [[DECL]],
// CK1: store double* [[VAL]], double** [[PVT:%.+]],
@@ -53,12 +52,11 @@ void foo(float *&lr, T *&tr) {
// CK1: getelementptr inbounds double, double* [[TTT]], i32 1
++g;
- // CK1-DAG: [[RVAL:%.+]] = bitcast float* [[T1:%.+]] to i8*
- // CK1-DAG: [[T1]] = load float*, float** [[DECL:%.+]],
+ // CK1: [[T1:%.+]] = load float*, float** [[DECL:%.+]],
// CK1: [[BP:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* %{{.+}}, i32 0, i32 0
- // CK1: store i8* [[RVAL]], i8** [[BP]],
- // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE01]]
// CK1: [[CBP:%.+]] = bitcast i8** [[BP]] to float**
+ // CK1: store float* [[T1]], float** [[CBP]],
+ // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE01]]
// CK1: [[VAL:%.+]] = load float*, float** [[CBP]],
// CK1-NOT: store float* [[VAL]], float** [[DECL]],
// CK1: store float* [[VAL]], float** [[PVT:%.+]],
@@ -85,12 +83,11 @@ void foo(float *&lr, T *&tr) {
// CK1: getelementptr inbounds float, float* [[TTT]], i32 1
++l;
- // CK1-DAG: [[RVAL:%.+]] = bitcast float* [[T1:%.+]] to i8*
- // CK1-DAG: [[T1]] = load float*, float** [[DECL:%.+]],
+ // CK1: [[T1:%.+]] = load float*, float** [[DECL:%.+]],
// CK1: [[BP:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* %{{.+}}, i32 0, i32 0
- // CK1: store i8* [[RVAL]], i8** [[BP]],
- // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE03]]
// CK1: [[CBP:%.+]] = bitcast i8** [[BP]] to float**
+ // CK1: store float* [[T1]], float** [[CBP]],
+ // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE03]]
// CK1: [[VAL:%.+]] = load float*, float** [[CBP]],
// CK1-NOT: store float* [[VAL]], float** [[DECL]],
// CK1: store float* [[VAL]], float** [[PVT:%.+]],
@@ -109,12 +106,11 @@ void foo(float *&lr, T *&tr) {
// CK1: br i1 [[CMP]], label %[[BTHEN:.+]], label %[[BELSE:.+]]
// CK1: [[BTHEN]]:
- // CK1-DAG: [[RVAL:%.+]] = bitcast float* [[T1:%.+]] to i8*
- // CK1-DAG: [[T1]] = load float*, float** [[DECL:%.+]],
+ // CK1: [[T1:%.+]] = load float*, float** [[DECL:%.+]],
// CK1: [[BP:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* %{{.+}}, i32 0, i32 0
- // CK1: store i8* [[RVAL]], i8** [[BP]],
- // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE04]]
// CK1: [[CBP:%.+]] = bitcast i8** [[BP]] to float**
+ // CK1: store float* [[T1]], float** [[CBP]],
+ // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE04]]
// CK1: [[VAL:%.+]] = load float*, float** [[CBP]],
// CK1-NOT: store float* [[VAL]], float** [[DECL]],
// CK1: store float* [[VAL]], float** [[PVT:%.+]],
@@ -146,13 +142,12 @@ void foo(float *&lr, T *&tr) {
// CK1: getelementptr inbounds float, float* [[TTT]], i32 1
++l;
- // CK1-DAG: [[RVAL:%.+]] = bitcast float* [[T1:%.+]] to i8*
- // CK1-DAG: [[T1]] = load float*, float** [[T2:%.+]],
- // CK1-DAG: [[T2]] = load float**, float*** [[DECL:%.+]],
+ // CK1: [[T2:%.+]] = load float**, float*** [[DECL:%.+]],
+ // CK1: [[T1:%.+]] = load float*, float** [[T2]],
// CK1: [[BP:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* %{{.+}}, i32 0, i32 0
- // CK1: store i8* [[RVAL]], i8** [[BP]],
- // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE05]]
// CK1: [[CBP:%.+]] = bitcast i8** [[BP]] to float**
+ // CK1: store float* [[T1]], float** [[CBP]],
+ // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE05]]
// CK1: [[VAL:%.+]] = load float*, float** [[CBP]],
// CK1: store float* [[VAL]], float** [[PVTV:%.+]],
// CK1-NOT: store float** [[PVTV]], float*** [[DECL]],
@@ -170,12 +165,11 @@ void foo(float *&lr, T *&tr) {
// CK1: getelementptr inbounds float, float* [[TTTT]], i32 1
++lr;
- // CK1-DAG: [[RVAL:%.+]] = bitcast i32* [[T1:%.+]] to i8*
- // CK1-DAG: [[T1]] = load i32*, i32** [[DECL:%.+]],
+ // CK1: [[T1:%.+]] = load i32*, i32** [[DECL:%.+]],
// CK1: [[BP:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* %{{.+}}, i32 0, i32 0
- // CK1: store i8* [[RVAL]], i8** [[BP]],
- // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE06]]
// CK1: [[CBP:%.+]] = bitcast i8** [[BP]] to i32**
+ // CK1: store i32* [[T1]], i32** [[CBP]],
+ // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE06]]
// CK1: [[VAL:%.+]] = load i32*, i32** [[CBP]],
// CK1-NOT: store i32* [[VAL]], i32** [[DECL]],
// CK1: store i32* [[VAL]], i32** [[PVT:%.+]],
@@ -190,13 +184,12 @@ void foo(float *&lr, T *&tr) {
// CK1: getelementptr inbounds i32, i32* [[TTT]], i32 1
++t;
- // CK1-DAG: [[RVAL:%.+]] = bitcast i32* [[T1:%.+]] to i8*
- // CK1-DAG: [[T1]] = load i32*, i32** [[T2:%.+]],
- // CK1-DAG: [[T2]] = load i32**, i32*** [[DECL:%.+]],
+ // CK1: [[T2:%.+]] = load i32**, i32*** [[DECL:%.+]],
+ // CK1: [[T1:%.+]] = load i32*, i32** [[T2]],
// CK1: [[BP:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* %{{.+}}, i32 0, i32 0
- // CK1: store i8* [[RVAL]], i8** [[BP]],
- // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE07]]
// CK1: [[CBP:%.+]] = bitcast i8** [[BP]] to i32**
+ // CK1: store i32* [[T1]], i32** [[CBP]],
+ // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE07]]
// CK1: [[VAL:%.+]] = load i32*, i32** [[CBP]],
// CK1: store i32* [[VAL]], i32** [[PVTV:%.+]],
// CK1-NOT: store i32** [[PVTV]], i32*** [[DECL]],
@@ -214,12 +207,11 @@ void foo(float *&lr, T *&tr) {
// CK1: getelementptr inbounds i32, i32* [[TTTT]], i32 1
++tr;
- // CK1-DAG: [[RVAL:%.+]] = bitcast float* [[T1:%.+]] to i8*
- // CK1-DAG: [[T1]] = load float*, float** [[DECL:%.+]],
+ // CK1: [[T1:%.+]] = load float*, float** [[DECL:%.+]],
// CK1: [[BP:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* %{{.+}}, i32 0, i32
- // CK1: store i8* [[RVAL]], i8** [[BP]],
- // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE08]]
// CK1: [[CBP:%.+]] = bitcast i8** [[BP]] to float**
+ // CK1: store float* [[T1]], float** [[CBP]],
+ // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE08]]
// CK1: [[VAL:%.+]] = load float*, float** [[CBP]],
// CK1-NOT: store float* [[VAL]], float** [[DECL]],
// CK1: store float* [[VAL]], float** [[PVT:%.+]],
@@ -235,11 +227,11 @@ void foo(float *&lr, T *&tr) {
++l; ++t;
- // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE09]]
// CK1: [[_CBP:%.+]] = bitcast i8** {{%.+}} to float**
+ // CK1: [[CBP:%.+]] = bitcast i8** {{%.+}} to i32**
+ // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE09]]
// CK1: [[_VAL:%.+]] = load float*, float** [[_CBP]],
// CK1: store float* [[_VAL]], float** [[_PVT:%.+]],
- // CK1: [[CBP:%.+]] = bitcast i8** {{%.+}} to i32**
// CK1: [[VAL:%.+]] = load i32*, i32** [[CBP]],
// CK1: store i32* [[VAL]], i32** [[PVT:%.+]],
// CK1: [[_TT1:%.+]] = load float*, float** [[_PVT]],
@@ -257,11 +249,11 @@ void foo(float *&lr, T *&tr) {
// CK1: getelementptr inbounds i32, i32* [[TTT]], i32 1
++l; ++t;
- // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE10]]
// CK1: [[_CBP:%.+]] = bitcast i8** {{%.+}} to float**
+ // CK1: [[CBP:%.+]] = bitcast i8** {{%.+}} to i32**
+ // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE10]]
// CK1: [[_VAL:%.+]] = load float*, float** [[_CBP]],
// CK1: store float* [[_VAL]], float** [[_PVT:%.+]],
- // CK1: [[CBP:%.+]] = bitcast i8** {{%.+}} to i32**
// CK1: [[VAL:%.+]] = load i32*, i32** [[CBP]],
// CK1: store i32* [[VAL]], i32** [[PVT:%.+]],
// CK1: [[_TT1:%.+]] = load float*, float** [[_PVT]],
@@ -279,12 +271,11 @@ void foo(float *&lr, T *&tr) {
// CK1: getelementptr inbounds i32, i32* [[TTT]], i32 1
++l; ++t;
- // CK1-DAG: [[RVAL:%.+]] = bitcast i32* [[T1:%.+]] to i8*
- // CK1-DAG: [[T1]] = load i32*, i32** [[DECL:%.+]],
+ // CK1: [[T1:%.+]] = load i32*, i32** [[DECL:%.+]],
// CK1: [[BP:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* %{{.+}}, i32 0, i32 0
- // CK1: store i8* [[RVAL]], i8** [[BP]],
- // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE11]]
// CK1: [[CBP:%.+]] = bitcast i8** [[BP]] to i32**
+ // CK1: store i32* [[T1]], i32** [[CBP]],
+ // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE11]]
// CK1: [[VAL:%.+]] = load i32*, i32** [[CBP]],
// CK1-NOT: store i32* [[VAL]], i32** [[DECL]],
// CK1: store i32* [[VAL]], i32** [[PVT:%.+]],
@@ -299,13 +290,12 @@ void foo(float *&lr, T *&tr) {
// CK1: getelementptr inbounds i32, i32* [[TTT]], i32 1
++l; ++t;
- // CK1-DAG: [[RVAL:%.+]] = bitcast i32* [[T1:%.+]] to i8*
- // CK1-DAG: [[T1]] = load i32*, i32** [[T2:%.+]],
- // CK1-DAG: [[T2]] = load i32**, i32*** [[DECL:%.+]],
+ // CK1: [[T2:%.+]] = load i32**, i32*** [[DECL:%.+]],
+ // CK1: [[T1:%.+]] = load i32*, i32** [[T2]],
// CK1: [[BP:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* %{{.+}}, i32 0, i32 0
- // CK1: store i8* [[RVAL]], i8** [[BP]],
- // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE12]]
// CK1: [[CBP:%.+]] = bitcast i8** [[BP]] to i32**
+ // CK1: store i32* [[T1]], i32** [[CBP]],
+ // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE12]]
// CK1: [[VAL:%.+]] = load i32*, i32** [[CBP]],
// CK1: store i32* [[VAL]], i32** [[PVTV:%.+]],
// CK1-NOT: store i32** [[PVTV]], i32*** [[DECL]],
@@ -356,10 +346,11 @@ struct ST {
int *la = 0;
// CK2: [[BP:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* %{{.+}}, i32 0, i32 1
- // CK2: store i8* [[RVAL:%.+]], i8** [[BP]],
+ // CK2: [[CBP:%.+]] = bitcast i8** [[BP]] to double***
+ // CK2: store double** [[RVAL:%.+]], double*** [[CBP]],
// CK2: call void @__tgt_target_data_begin{{.+}}[[MTYPE00]]
- // CK2: [[CBP:%.+]] = bitcast i8** [[BP]] to double**
- // CK2: [[VAL:%.+]] = load double*, double** [[CBP]],
+ // CK2: [[CBP1:%.+]] = bitcast double*** [[CBP]] to double**
+ // CK2: [[VAL:%.+]] = load double*, double** [[CBP1]],
// CK2: store double* [[VAL]], double** [[PVT:%.+]],
// CK2: store double** [[PVT]], double*** [[PVT2:%.+]],
// CK2: [[TT1:%.+]] = load double**, double*** [[PVT2]],
@@ -376,10 +367,11 @@ struct ST {
a++;
// CK2: [[BP:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* %{{.+}}, i32 0, i32 2
- // CK2: store i8* [[RVAL:%.+]], i8** [[BP]],
+ // CK2: [[CBP:%.+]] = bitcast i8** [[BP]] to double***
+ // CK2: store double** [[RVAL:%.+]], double*** [[CBP]],
// CK2: call void @__tgt_target_data_begin{{.+}}[[MTYPE01]]
- // CK2: [[CBP:%.+]] = bitcast i8** [[BP]] to double**
- // CK2: [[VAL:%.+]] = load double*, double** [[CBP]],
+ // CK2: [[CBP1:%.+]] = bitcast double*** [[CBP]] to double**
+ // CK2: [[VAL:%.+]] = load double*, double** [[CBP1]],
// CK2: store double* [[VAL]], double** [[PVT:%.+]],
// CK2: store double** [[PVT]], double*** [[PVT2:%.+]],
// CK2: [[TT1:%.+]] = load double**, double*** [[PVT2]],
@@ -397,9 +389,9 @@ struct ST {
b++;
// CK2: [[BP:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* %{{.+}}, i32 0, i32 0
- // CK2: store i8* [[RVAL:%.+]], i8** [[BP]],
- // CK2: call void @__tgt_target_data_begin{{.+}}[[MTYPE02]]
// CK2: [[CBP:%.+]] = bitcast i8** [[BP]] to double**
+ // CK2: store double* [[RVAL:%.+]], double** [[CBP]],
+ // CK2: call void @__tgt_target_data_begin{{.+}}[[MTYPE02]]
// CK2: [[VAL:%.+]] = load double*, double** [[CBP]],
// CK2: store double* [[VAL]], double** [[PVT:%.+]],
// CK2: store double** [[PVT]], double*** [[PVT2:%.+]],
@@ -419,16 +411,17 @@ struct ST {
la++;
// CK2: [[BP:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* %{{.+}}, i32 0, i32 0
- // CK2: store i8* [[RVAL:%.+]], i8** [[BP]],
+ // CK2: [[CBP:%.+]] = bitcast i8** [[BP]] to double**
+ // CK2: store double* [[RVAL:%.+]], double** [[CBP]],
// CK2: [[_BP:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* %{{.+}}, i32 0, i32 3
- // CK2: store i8* [[_RVAL:%.+]], i8** [[_BP]],
+ // CK2: [[_CBP:%.+]] = bitcast i8** [[_BP]] to double***
+ // CK2: store double** [[_RVAL:%.+]], double*** [[_CBP]],
// CK2: call void @__tgt_target_data_begin{{.+}}[[MTYPE03]]
- // CK2: [[CBP:%.+]] = bitcast i8** [[BP]] to double**
// CK2: [[VAL:%.+]] = load double*, double** [[CBP]],
// CK2: store double* [[VAL]], double** [[PVT:%.+]],
// CK2: store double** [[PVT]], double*** [[PVT2:%.+]],
- // CK2: [[_CBP:%.+]] = bitcast i8** [[_BP]] to double**
- // CK2: [[_VAL:%.+]] = load double*, double** [[_CBP]],
+ // CK2: [[_CBP1:%.+]] = bitcast double*** [[_CBP]] to double**
+ // CK2: [[_VAL:%.+]] = load double*, double** [[_CBP1]],
// CK2: store double* [[_VAL]], double** [[_PVT:%.+]],
// CK2: store double** [[_PVT]], double*** [[_PVT2:%.+]],
// CK2: [[TT1:%.+]] = load double**, double*** [[PVT2]],
diff --git a/test/OpenMP/target_enter_data_codegen.cpp b/test/OpenMP/target_enter_data_codegen.cpp
index 152cd46b4a2f..683cd976d395 100644
--- a/test/OpenMP/target_enter_data_codegen.cpp
+++ b/test/OpenMP/target_enter_data_codegen.cpp
@@ -45,8 +45,10 @@ void foo(int arg) {
// CK1-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
// CK1-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
- // CK1-DAG: store i8* bitcast ([100 x double]* @gc to i8*), i8** [[BP0]]
- // CK1-DAG: store i8* bitcast ([100 x double]* @gc to i8*), i8** [[P0]]
+ // CK1-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [100 x double]**
+ // CK1-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [100 x double]**
+ // CK1-DAG: store [100 x double]* @gc, [100 x double]** [[CBP0]]
+ // CK1-DAG: store [100 x double]* @gc, [100 x double]** [[CP0]]
// CK1: %{{.+}} = add nsw i32 %{{[^,]+}}, 1
// CK1-NOT: __tgt_target_data_end
@@ -67,10 +69,10 @@ void foo(int arg) {
// CK1-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
// CK1-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
- // CK1-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]]
- // CK1-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]]
- // CK1-DAG: [[CBPVAL0]] = bitcast i32* [[VAR0:%.+]] to i8*
- // CK1-DAG: [[CPVAL0]] = bitcast i32* [[VAR0]] to i8*
+ // CK1-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i32**
+ // CK1-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32**
+ // CK1-DAG: store i32* [[VAR0:%.+]], i32** [[CBP0]]
+ // CK1-DAG: store i32* [[VAR0]], i32** [[CP0]]
// CK1: br label %[[IFEND:[^,]+]]
// CK1: [[IFELSE]]
@@ -93,11 +95,11 @@ void foo(int arg) {
// CK1-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
// CK1-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
// CK1-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0
- // CK1-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]]
- // CK1-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]]
+ // CK1-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to float**
+ // CK1-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to float**
+ // CK1-DAG: store float* [[VAR0:%.+]], float** [[CBP0]]
+ // CK1-DAG: store float* [[VAR0]], float** [[CP0]]
// CK1-DAG: store i[[sz]] [[CSVAL0:%[^,]+]], i[[sz]]* [[S0]]
- // CK1-DAG: [[CBPVAL0]] = bitcast float* [[VAR0:%.+]] to i8*
- // CK1-DAG: [[CPVAL0]] = bitcast float* [[VAR0]] to i8*
// CK1-DAG: [[CSVAL0]] = mul nuw i[[sz]] %{{[^,]+}}, 4
// CK1: %{{.+}} = add nsw i32 %{{[^,]+}}, 1
// CK1-NOT: __tgt_target_data_end
@@ -114,15 +116,18 @@ void foo(int arg) {
// CK1-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
// CK1-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
- // CK1-DAG: store i8* bitcast ([[ST]]* @gb to i8*), i8** [[BP0]]
- // CK1-DAG: store i8* bitcast (double** getelementptr inbounds ([[ST]], [[ST]]* @gb, i32 0, i32 1) to i8*), i8** [[P0]]
+ // CK1-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]**
+ // CK1-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to double***
+ // CK1-DAG: store [[ST]]* @gb, [[ST]]** [[CBP0]]
+ // CK1-DAG: store double** getelementptr inbounds ([[ST]], [[ST]]* @gb, i32 0, i32 1), double*** [[CP0]]
// CK1-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
// CK1-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
- // CK1-DAG: store i8* bitcast (double** getelementptr inbounds ([[ST]], [[ST]]* @gb, i32 0, i32 1) to i8*), i8** [[BP1]]
- // CK1-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]]
- // CK1-DAG: [[CPVAL1]] = bitcast double* [[SEC1:%.+]] to i8*
+ // CK1-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to double***
+ // CK1-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to double**
+ // CK1-DAG: store double** getelementptr inbounds ([[ST]], [[ST]]* @gb, i32 0, i32 1), double*** [[CBP1]]
+ // CK1-DAG: store double* [[SEC1:%.+]], double** [[CP1]]
// CK1-DAG: [[SEC1]] = getelementptr inbounds {{.+}}double* [[SEC11:%[^,]+]], i{{.+}} 0
// CK1-DAG: [[SEC11]] = load double*, double** getelementptr inbounds ([[ST]], [[ST]]* @gb, i32 0, i32 1),
@@ -174,19 +179,19 @@ int bar(int arg){
// CK2-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
// CK2-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
-// CK2-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]]
-// CK2-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]]
-// CK2-DAG: [[CBPVAL0]] = bitcast [[ST]]* [[VAR0:%.+]] to i8*
-// CK2-DAG: [[CPVAL0]] = bitcast double** [[SEC0:%[^,]+]] to i8*
+// CK2-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]**
+// CK2-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to double***
+// CK2-DAG: store [[ST]]* [[VAR0:%.+]], [[ST]]** [[CBP0]]
+// CK2-DAG: store double** [[SEC0:%.+]], double*** [[CP0]]
// CK2-DAG: [[SEC0]] = getelementptr inbounds {{.*}}[[ST]]* [[VAR0]], i32 0, i32 1
// CK2-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
// CK2-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
-// CK2-DAG: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]]
-// CK2-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]]
-// CK2-DAG: [[CBPVAL1]] = bitcast double** [[SEC0]] to i8*
-// CK2-DAG: [[CPVAL1]] = bitcast double* [[SEC1:%[^,]+]] to i8*
+// CK2-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to double***
+// CK2-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to double**
+// CK2-DAG: store double** [[SEC0]], double*** [[CBP1]]
+// CK2-DAG: store double* [[SEC1:%.+]], double** [[CP1]]
// CK2-DAG: [[SEC1]] = getelementptr inbounds {{.*}}double* [[SEC11:%[^,]+]], i{{.+}} 1
// CK2-DAG: [[SEC11]] = load double*, double** [[SEC111:%[^,]+]],
// CK2-DAG: [[SEC111]] = getelementptr inbounds {{.*}}[[ST]]* [[VAR0]], i32 0, i32 1
diff --git a/test/OpenMP/target_exit_data_codegen.cpp b/test/OpenMP/target_exit_data_codegen.cpp
index d3a38592a610..a82c1c6c4aac 100644
--- a/test/OpenMP/target_exit_data_codegen.cpp
+++ b/test/OpenMP/target_exit_data_codegen.cpp
@@ -46,8 +46,10 @@ void foo(int arg) {
// CK1-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
// CK1-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
- // CK1-DAG: store i8* bitcast ([100 x double]* @gc to i8*), i8** [[BP0]]
- // CK1-DAG: store i8* bitcast ([100 x double]* @gc to i8*), i8** [[P0]]
+ // CK1-DAG: [[BPC0:%.+]] = bitcast i8** [[BP0]] to [100 x double]**
+ // CK1-DAG: [[PC0:%.+]] = bitcast i8** [[P0]] to [100 x double]**
+ // CK1-DAG: store [100 x double]* @gc, [100 x double]** [[BPC0]]
+ // CK1-DAG: store [100 x double]* @gc, [100 x double]** [[PC0]]
// CK1: %{{.+}} = add nsw i32 %{{[^,]+}}, 1
#pragma omp target exit data if(1+3-5) device(arg) map(from: gc)
@@ -68,10 +70,10 @@ void foo(int arg) {
// CK1-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
// CK1-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
- // CK1-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]]
- // CK1-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]]
- // CK1-DAG: [[CBPVAL0]] = bitcast i32* [[VAR0:%.+]] to i8*
- // CK1-DAG: [[CPVAL0]] = bitcast i32* [[VAR0]] to i8*
+ // CK1-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i32**
+ // CK1-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32**
+ // CK1-DAG: store i32* [[VAL0:%[^,]+]], i32** [[CBP0]]
+ // CK1-DAG: store i32* [[VAL0]], i32** [[CP0]]
// CK1: br label %[[IFEND:[^,]+]]
// CK1: [[IFELSE]]
@@ -94,11 +96,11 @@ void foo(int arg) {
// CK1-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
// CK1-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
// CK1-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0
- // CK1-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]]
- // CK1-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]]
+ // CK1-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to float**
+ // CK1-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to float**
+ // CK1-DAG: store float* [[VAL0:%[^,]+]], float** [[CBP0]]
+ // CK1-DAG: store float* [[VAL0]], float** [[CP0]]
// CK1-DAG: store i[[sz]] [[CSVAL0:%[^,]+]], i[[sz]]* [[S0]]
- // CK1-DAG: [[CBPVAL0]] = bitcast float* [[VAR0:%.+]] to i8*
- // CK1-DAG: [[CPVAL0]] = bitcast float* [[VAR0]] to i8*
// CK1-DAG: [[CSVAL0]] = mul nuw i[[sz]] %{{[^,]+}}, 4
// CK1: %{{.+}} = add nsw i32 %{{[^,]+}}, 1
#pragma omp target exit data map(always, from: lb)
@@ -115,15 +117,18 @@ void foo(int arg) {
// CK1-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
// CK1-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
- // CK1-DAG: store i8* bitcast ([[ST]]* @gb to i8*), i8** [[BP0]]
- // CK1-DAG: store i8* bitcast (double** getelementptr inbounds ([[ST]], [[ST]]* @gb, i32 0, i32 1) to i8*), i8** [[P0]]
+ // CK1-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]**
+ // CK1-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to double***
+ // CK1-DAG: store [[ST]]* @gb, [[ST]]** [[CBP0]]
+ // CK1-DAG: store double** getelementptr inbounds ([[ST]], [[ST]]* @gb, i32 0, i32 1), double*** [[CP0]]
// CK1-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
// CK1-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
- // CK1-DAG: store i8* bitcast (double** getelementptr inbounds ([[ST]], [[ST]]* @gb, i32 0, i32 1) to i8*), i8** [[BP1]]
- // CK1-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]]
- // CK1-DAG: [[CPVAL1]] = bitcast double* [[SEC1:%.+]] to i8*
+ // CK1-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to double***
+ // CK1-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to double**
+ // CK1-DAG: store double** getelementptr inbounds ([[ST]], [[ST]]* @gb, i32 0, i32 1), double*** [[CBP1]]
+ // CK1-DAG: store double* [[SEC1:%[^,]+]], double** [[CP1]]
// CK1-DAG: [[SEC1]] = getelementptr inbounds {{.+}}double* [[SEC11:%[^,]+]], i{{.+}} 0
// CK1-DAG: [[SEC11]] = load double*, double** getelementptr inbounds ([[ST]], [[ST]]* @gb, i32 0, i32 1),
@@ -175,19 +180,19 @@ int bar(int arg){
// CK2-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
// CK2-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
-// CK2-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]]
-// CK2-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]]
-// CK2-DAG: [[CBPVAL0]] = bitcast [[ST]]* [[VAR0:%.+]] to i8*
-// CK2-DAG: [[CPVAL0]] = bitcast double** [[SEC0:%[^,]+]] to i8*
+// CK2-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]**
+// CK2-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to double***
+// CK2-DAG: store [[ST]]* [[VAR0:%[^,]+]], [[ST]]** [[CBP0]]
+// CK2-DAG: store double** [[SEC0:%[^,]+]], double*** [[CP0]]
// CK2-DAG: [[SEC0]] = getelementptr inbounds {{.*}}[[ST]]* [[VAR0]], i32 0, i32 1
// CK2-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
// CK2-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
-// CK2-DAG: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]]
-// CK2-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]]
-// CK2-DAG: [[CBPVAL1]] = bitcast double** [[SEC0]] to i8*
-// CK2-DAG: [[CPVAL1]] = bitcast double* [[SEC1:%[^,]+]] to i8*
+// CK2-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to double***
+// CK2-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to double**
+// CK2-DAG: store double** [[SEC0]], double*** [[CBP1]]
+// CK2-DAG: store double* [[SEC1:%[^,]+]], double** [[CP1]]
// CK2-DAG: [[SEC1]] = getelementptr inbounds {{.*}}double* [[SEC11:%[^,]+]], i{{.+}} 1
// CK2-DAG: [[SEC11]] = load double*, double** [[SEC111:%[^,]+]],
// CK2-DAG: [[SEC111]] = getelementptr inbounds {{.*}}[[ST]]* [[VAR0]], i32 0, i32 1
diff --git a/test/OpenMP/target_firstprivate_codegen.cpp b/test/OpenMP/target_firstprivate_codegen.cpp
index a9af2d02f237..1fb0ef9e848c 100644
--- a/test/OpenMP/target_firstprivate_codegen.cpp
+++ b/test/OpenMP/target_firstprivate_codegen.cpp
@@ -93,12 +93,12 @@ int foo(int n, double *ptr) {
// CHECK-64: store i{{[0-9]+}} [[AVAL]], i{{[0-9]+}}* [[CONV]],
// CHECK-32: store i{{[0-9]+}} [[AVAL]], i{{[0-9]+}}* [[ACAST]],
// CHECK: [[ACAST_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[ACAST]],
- // CHECK: [[ACAST_TOPTR:%.+]] = inttoptr i{{[0-9]+}} [[ACAST_VAL]] to i8*
// CHECK: [[BASE_PTR_GEP:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[BASE_PTR_ARR]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
- // CHECK: store i8* [[ACAST_TOPTR]], i8** [[BASE_PTR_GEP]],
- // CHECK: [[ACAST_TOPTR2:%.+]] = inttoptr i{{[0-9]+}} [[ACAST_VAL]] to i8*
+ // CHECK: [[ACAST_TOPTR:%.+]] = bitcast i8** [[BASE_PTR_GEP]] to i{{[0-9]+}}*
+ // CHECK: store i{{[0-9]+}} [[ACAST_VAL]], i{{[0-9]+}}* [[ACAST_TOPTR]],
// CHECK: [[PTR_GEP:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[PTR_ARR]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
- // CHECK: store i8* [[ACAST_TOPTR2]], i8** [[PTR_GEP]],
+ // CHECK: [[ACAST_TOPTR2:%.+]] = bitcast i8** [[PTR_GEP]] to i{{[0-9]+}}*
+ // CHECK: store i{{[0-9]+}} [[ACAST_VAL]], i{{[0-9]+}}* [[ACAST_TOPTR2]],
// CHECK: [[BASE_PTR_GEP_ARG:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[BASE_PTR_ARR]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: [[PTR_GEP_ARG:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[PTR_ARR]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: {{.+}} = call i32 @__tgt_target(i32 -1, {{.+}}, i32 1, i8** [[BASE_PTR_GEP_ARG]], i8** [[PTR_GEP_ARG]], i[[SZ]]* getelementptr inbounds ([1 x i[[SZ]]], [1 x i[[SZ]]]* [[SIZET]], i32 0, i32 0), i32* getelementptr inbounds ([1 x i32], [1 x i32]* [[MAPT]], i32 0, i32 0))
@@ -132,85 +132,87 @@ int foo(int n, double *ptr) {
// CHECK: [[CN_SIZE_2:%.+]] = mul{{.+}} i{{[0-9]+}} [[CN_SIZE_1]], 8
// firstprivate(aa) --> base_ptr = aa, ptr = aa, size = 2 (short)
- // CHECK: [[A2CAST_TO_INT:%.+]] = inttoptr i{{[0-9]+}} [[A2CAST_VAL]] to i8*
// CHECK: [[BASE_PTR_GEP2_0:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BASE_PTR_ARR2]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
- // CHECK: store i8* [[A2CAST_TO_INT]], i8** [[BASE_PTR_GEP2_0]],
- // CHECK: [[A2CAST_TO_INT_2:%.+]] = inttoptr i{{[0-9]+}} [[A2CAST_VAL]] to i8*
+ // CHECK: [[ACAST_TOPTR:%.+]] = bitcast i8** [[BASE_PTR_GEP2_0]] to i{{[0-9]+}}*
+ // CHECK: store i{{[0-9]+}} [[A2CAST_VAL]], i{{[0-9]+}}* [[ACAST_TOPTR]],
// CHECK: [[PTR_GEP2_0:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[PTR_ARR2]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
- // CHECK: store i8* [[A2CAST_TO_INT_2]], i8** [[PTR_GEP2_0]],
+ // CHECK: [[ACAST_TOPTR:%.+]] = bitcast i8** [[PTR_GEP2_0]] to i{{[0-9]+}}*
+ // CHECK: store i{{[0-9]+}} [[A2CAST_VAL]], i{{[0-9]+}}* [[ACAST_TOPTR]],
// CHECK: [[SIZE_GEPA2:%.+]] = getelementptr inbounds [9 x i{{[0-9]+}}], [9 x i{{[0-9]+}}]* [[SIZET2]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: store i{{[0-9]+}} 2, i{{[0-9]+}}* [[SIZE_GEPA2]],
// firstprivate(b): base_ptr = &b[0], ptr = &b[0], size = 40 (sizeof(float)*10)
- // CHECK: [[BCAST:%.+]] = bitcast [10 x float]* [[B]] to i8*
// CHECK: [[BASE_PTR_GEP2_1:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BASE_PTR_ARR2]], i{{[0-9]+}} 0, i{{[0-9]+}} 1
- // CHECK: store i8* [[BCAST]], i8** [[BASE_PTR_GEP2_1]],
- // CHECK: [[BCAST2:%.+]] = bitcast [10 x float]* [[B]] to i8*
+ // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[BASE_PTR_GEP2_1]] to [10 x float]**
+ // CHECK: store [10 x float]* [[B]], [10 x float]** [[BCAST_TOPTR]],
// CHECK: [[PTR_GEP2_1:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[PTR_ARR2]], i{{[0-9]+}} 0, i{{[0-9]+}} 1
- // CHECK: store i8* [[BCAST2]], i8** [[PTR_GEP2_1]],
+ // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[PTR_GEP2_1]] to [10 x float]**
+ // CHECK: store [10 x float]* [[B]], [10 x float]** [[BCAST_TOPTR]],
// CHECK: [[SIZE_GEPB:%.+]] = getelementptr inbounds [9 x i{{[0-9]+}}], [9 x i{{[0-9]+}}]* [[SIZET2]], i{{[0-9]+}} 0, i{{[0-9]+}} 1
// CHECK: store i{{[0-9]+}} 40, i{{[0-9]+}}* [[SIZE_GEPB]],
// firstprivate(bn), 2 entries, n and bn: (1) base_ptr = n, ptr = n, size = 8 ; (2) base_ptr = &c[0], ptr = &c[0], size = n*sizeof(float)
- // CHECK-64: [[N_EXT3_1:%.+]] = inttoptr i{{[0-9]+}} [[N_EXT]] to i8*
- // CHECK-32: [[N_EXT3_1:%.+]] = inttoptr i{{[0-9]+}} [[N_ADDR_VAL]] to i8*
// CHECK: [[BASE_PTR_GEP2_2:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BASE_PTR_ARR2]], i{{[0-9]+}} 0, i{{[0-9]+}} 2
- // CHECK: store i8* [[N_EXT3_1]], i8** [[BASE_PTR_GEP2_2]],
- // CHECK-64: [[N_EXT3_2:%.+]] = inttoptr i{{[0-9]+}} [[N_EXT]] to i8*
- // CHECK-32: [[N_EXT3_2:%.+]] = inttoptr i{{[0-9]+}} [[N_ADDR_VAL]] to i8*
+ // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[BASE_PTR_GEP2_2]] to i{{[0-9]+}}*
+ // CHECK-64: store i{{[0-9]+}} [[N_EXT]], i{{[0-9]+}}* [[BCAST_TOPTR]],
+ // CHECK-32: store i{{[0-9]+}} [[N_ADDR_VAL]], i{{[0-9]+}}* [[BCAST_TOPTR]],
// CHECK: [[PTR_GEP2_2:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[PTR_ARR2]], i{{[0-9]+}} 0, i{{[0-9]+}} 2
- // CHECK: store i8* [[N_EXT3_2]], i8** [[PTR_GEP2_2]],
+ // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[PTR_GEP2_2]] to i{{[0-9]+}}*
+ // CHECK-64: store i{{[0-9]+}} [[N_EXT]], i{{[0-9]+}}* [[BCAST_TOPTR]],
+ // CHECK-32: store i{{[0-9]+}} [[N_ADDR_VAL]], i{{[0-9]+}}* [[BCAST_TOPTR]],
// CHECK: [[SIZE_GEPBN_1:%.+]] = getelementptr inbounds [9 x i{{[0-9]+}}], [9 x i{{[0-9]+}}]* [[SIZET2]], i{{[0-9]+}} 0, i{{[0-9]+}} 2
// CHECK: store i{{[0-9]+}} {{[0-9]}}, i{{[0-9]+}}* [[SIZE_GEPBN_1]],
- // CHECK: [[VLABN_BCAST:%.+]] = bitcast float* [[BN_VLA]] to i8*
// CHECK: [[BASE_PTR_GEP2_3:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BASE_PTR_ARR2]], i{{[0-9]+}} 0, i{{[0-9]+}} 3
- // CHECK: store i8* [[VLABN_BCAST]], i8** [[BASE_PTR_GEP2_3]],
+ // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[BASE_PTR_GEP2_3]] to float**
+ // CHECK: store float* [[BN_VLA]], float** [[BCAST_TOPTR]],
// CHECK: [[SIZE_GEPBN_3:%.+]] = getelementptr inbounds [9 x i{{[0-9]+}}], [9 x i{{[0-9]+}}]* [[SIZET2]], i{{[0-9]+}} 0, i{{[0-9]+}} 3
// CHECK: store i{{[0-9]+}} [[BN_SIZE]], i{{[0-9]+}}* [[SIZE_GEPBN_3]]
// firstprivate(c): base_ptr = &c[0], ptr = &c[0], size = 400 (5*10*sizeof(double))
- // CHECK: [[C_BCAST:%.+]] = bitcast [5 x [10 x double]]* [[C]] to i8*
// CHECK: [[BASE_PTR_GEP2_4:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BASE_PTR_ARR2]], i{{[0-9]+}} 0, i{{[0-9]+}} 4
- // CHECK: store i8* [[C_BCAST]], i8** [[BASE_PTR_GEP2_4]],
- // CHECK: [[C_BCAST2:%.+]] = bitcast [5 x [10 x double]]* [[C]] to i8*
+ // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[BASE_PTR_GEP2_4]] to [5 x [10 x double]]**
+ // CHECK: store [5 x [10 x double]]* [[C]], [5 x [10 x double]]** [[BCAST_TOPTR]],
// CHECK: [[PTR_GEP2_4:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[PTR_ARR2]], i{{[0-9]+}} 0, i{{[0-9]+}} 4
- // CHECK: store i8* [[C_BCAST2]], i8** [[PTR_GEP2_4]],
+ // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[PTR_GEP2_4]] to [5 x [10 x double]]**
+ // CHECK: store [5 x [10 x double]]* [[C]], [5 x [10 x double]]** [[BCAST_TOPTR]],
// CHECK: [[SIZE_GEPC_4:%.+]] = getelementptr inbounds [9 x i{{[0-9]+}}], [9 x i{{[0-9]+}}]* [[SIZET2]], i{{[0-9]+}} 0, i{{[0-9]+}} 4
// CHECK: store i{{[0-9]+}} 400, i{{[0-9]+}}* [[SIZE_GEPC_4]],
// firstprivate(cn), 3 entries, 5, n, cn: (1) base_ptr = 5, ptr = 5, size = 8; (2) (1) base_ptr = n, ptr = n, size = 8; (3) base_ptr = &cn[0], ptr = &cn[0], size = 5*n*sizeof(double)
// CHECK: [[BASE_PTR_GEP2_5:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BASE_PTR_ARR2]], i{{[0-9]+}} 0, i{{[0-9]+}} 5
- // CHECK: store i8* inttoptr (i{{[0-9]+}} 5 to i8*), i8** [[BASE_PTR_GEP2_5]],
+ // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[BASE_PTR_GEP2_5]] to i{{[0-9]+}}*
+ // CHECK: store i{{[0-9]+}} 5, i{{[0-9]+}}* [[BCAST_TOPTR]],
// CHECK: [[PTR_GEP2_5:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[PTR_ARR2]], i{{[0-9]+}} 0, i{{[0-9]+}} 5
- // CHECK: store i8* inttoptr (i{{[0-9]+}} 5 to i8*), i8** [[PTR_GEP2_5]],
+ // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[PTR_GEP2_5]] to i{{[0-9]+}}*
+ // CHECK: store i{{[0-9]+}} 5, i{{[0-9]+}}* [[BCAST_TOPTR]],
// CHECK: [[SIZE_GEPCN_5:%.+]] = getelementptr inbounds [9 x i{{[0-9]+}}], [9 x i{{[0-9]+}}]* [[SIZET2]], i{{[0-9]+}} 0, i{{[0-9]+}} 5
// CHECK: store i{{[0-9]+}} {{[0-9]}}, i{{[0-9]+}}* [[SIZE_GEPCN_5]],
- // CHECK-64: [[CN_SZ_2_1:%.+]] = inttoptr i{{[0-9]+}} [[N_EXT2]] to i8*
- // CHECK-32: [[CN_SZ_2_1:%.+]] = inttoptr i{{[0-9]+}} [[N_ADDR_VAL2]] to i8*
// CHECK: [[BASE_PTR_GEP2_6:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BASE_PTR_ARR2]], i{{[0-9]+}} 0, i{{[0-9]+}} 6
- // CHECK: store i8* [[CN_SZ_2_1]], i8** [[BASE_PTR_GEP2_6]],
- // CHECK-64: [[CN_SZ_2_2:%.+]] = inttoptr i{{[0-9]+}} [[N_EXT2]] to i8*
- // CHECK-32: [[CN_SZ_2_2:%.+]] = inttoptr i{{[0-9]+}} [[N_ADDR_VAL2]] to i8*
+ // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[BASE_PTR_GEP2_6]] to i{{[0-9]+}}*
+ // CHECK-64: store i{{[0-9]+}} [[N_EXT2]], i{{[0-9]+}}* [[BCAST_TOPTR]],
+ // CHECK-32: store i{{[0-9]+}} [[N_ADDR_VAL2]], i{{[0-9]+}}* [[BCAST_TOPTR]],
// CHECK: [[PTR_GEP2_6:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[PTR_ARR2]], i{{[0-9]+}} 0, i{{[0-9]+}} 6
- // CHECK: store i8* [[CN_SZ_2_2]], i8** [[PTR_GEP2_6]],
+ // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[PTR_GEP2_6]] to i{{[0-9]+}}*
+ // CHECK-64: store i{{[0-9]+}} [[N_EXT2]], i{{[0-9]+}}* [[BCAST_TOPTR]],
+ // CHECK-32: store i{{[0-9]+}} [[N_ADDR_VAL2]], i{{[0-9]+}}* [[BCAST_TOPTR]],
// CHECK: [[SIZE_GEPCN_6:%.+]] = getelementptr inbounds [9 x i{{[0-9]+}}], [9 x i{{[0-9]+}}]* [[SIZET2]], i{{[0-9]+}} 0, i{{[0-9]+}} 6
// CHECK: store i{{[0-9]+}} {{[0-9]}}, i{{[0-9]+}}* [[SIZE_GEPCN_6]],
- // CHECK: [[VLA_CN_BCAST:%.+]] = bitcast double* [[CN_VLA]] to i8*
// CHECK: [[BASE_PTR_GEP2_7:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BASE_PTR_ARR2]], i{{[0-9]+}} 0, i{{[0-9]+}} 7
- // CHECK: store i8* [[VLA_CN_BCAST]], i8** [[BASE_PTR_GEP2_7]],
- // CHECK: [[VLA_CN_BCAST2:%.+]] = bitcast double* [[CN_VLA]] to i8*
+ // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[BASE_PTR_GEP2_7]] to double**
+ // CHECK: store double* [[CN_VLA]], double** [[BCAST_TOPTR]],
// CHECK: [[PTR_GEP2_7:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[PTR_ARR2]], i{{[0-9]+}} 0, i{{[0-9]+}} 7
- // CHECK: store i8* [[VLA_CN_BCAST2]], i8** [[PTR_GEP2_7]],
+ // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[PTR_GEP2_7]] to double**
+ // CHECK: store double* [[CN_VLA]], double** [[BCAST_TOPTR]],
// CHECK: [[SIZE_GEPCN_7:%.+]] = getelementptr inbounds [9 x i{{[0-9]+}}], [9 x i{{[0-9]+}}]* [[SIZET2]], i{{[0-9]+}} 0, i{{[0-9]+}} 7
// CHECK: store i{{[0-9]+}} [[CN_SIZE_2]], i{{[0-9]+}}* [[SIZE_GEPCN_7]],
// firstprivate(d): base_ptr = &d, ptr = &d, size = 16
- // CHECK: [[D_REF:%.+]] = bitcast [[TT]]* [[D]] to i8*
// CHECK: [[BASE_PTR_GEP2_8:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BASE_PTR_ARR2]], i{{[0-9]+}} 0, i{{[0-9]+}} 8
- // CHECK: store i8* [[D_REF]], i8** [[BASE_PTR_GEP2_8]],
- // CHECK: [[D_REF2:%.+]] = bitcast [[TT]]* [[D]] to i8*
+ // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[BASE_PTR_GEP2_8]] to [[TT]]**
+ // CHECK: store [[TT]]* [[D]], [[TT]]** [[BCAST_TOPTR]],
// CHECK: [[PTR_GEP2_8:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[PTR_ARR2]], i{{[0-9]+}} 0, i{{[0-9]+}} 8
- // CHECK: store i8* [[D_REF2]], i8** [[PTR_GEP2_8]],
+ // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[PTR_GEP2_8]] to [[TT]]**
+ // CHECK: store [[TT]]* [[D]], [[TT]]** [[BCAST_TOPTR]],
// CHECK: [[SIZE_GEPCN_8:%.+]] = getelementptr inbounds [9 x i{{[0-9]+}}], [9 x i{{[0-9]+}}]* [[SIZET2]], i{{[0-9]+}} 0, i{{[0-9]+}} 8
// CHECK: store i{{[0-9]+}} {{[0-9]+}}, i{{[0-9]+}}* [[SIZE_GEPCN_8]],
@@ -299,13 +301,13 @@ int foo(int n, double *ptr) {
ptr[0]++;
}
// CHECK: [[PTR_ADDR_REF:%.+]] = load double*, double** [[PTR_ADDR]],
- // CHECK: [[PTR_ADDR_BCAST:%.+]] = bitcast double* [[PTR_ADDR_REF]] to i8*
// CHECK: [[BASE_PTR_GEP3_0:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[BASE_PTR_ARR3]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
- // CHECK: store i8* [[PTR_ADDR_BCAST]], i8** [[BASE_PTR_GEP3_0]],
- // CHECK: [[PTR_ADDR_BCAST2:%.+]] = bitcast double* [[PTR_ADDR_REF]] to i8*
+ // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[BASE_PTR_GEP3_0]] to double**
+ // CHECK: store double* [[PTR_ADDR_REF]], double** [[BCAST_TOPTR]],
// CHECK: [[PTR_GEP3_0:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[PTR_ARR3]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
- // CHECK: store i8* [[PTR_ADDR_BCAST2]], i8** [[PTR_GEP3_0]],
+ // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[PTR_GEP3_0]] to double**
+ // CHECK: store double* [[PTR_ADDR_REF]], double** [[BCAST_TOPTR]],