From 0414e226b73ef7952be3ef346c1c802e7f036f54 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Wed, 13 Jan 2016 20:00:46 +0000 Subject: Vendor import of clang trunk r257626: https://llvm.org/svn/llvm-project/cfe/trunk@257626 --- include/clang/AST/ASTContext.h | 12 +- include/clang/AST/ASTMutationListener.h | 4 + include/clang/AST/BuiltinTypes.def | 2 +- include/clang/AST/Decl.h | 5 +- include/clang/AST/DeclBase.h | 9 +- include/clang/AST/Expr.h | 1 + include/clang/AST/ExprCXX.h | 35 +- include/clang/AST/OperationKinds.h | 6 +- include/clang/AST/RecursiveASTVisitor.h | 4 + include/clang/AST/Stmt.h | 2 +- include/clang/AST/Type.h | 42 +- include/clang/AST/TypeLoc.h | 19 + include/clang/AST/TypeNodes.def | 1 + include/clang/ASTMatchers/ASTMatchersInternal.h | 8 +- include/clang/Basic/DiagnosticDriverKinds.td | 1 + include/clang/Basic/DiagnosticGroups.td | 1 + include/clang/Basic/DiagnosticIDs.h | 2 +- include/clang/Basic/DiagnosticLexKinds.td | 2 + include/clang/Basic/DiagnosticSemaKinds.td | 5 +- include/clang/Basic/Specifiers.h | 5 + include/clang/Basic/TokenKinds.def | 7 + include/clang/Basic/VirtualFileSystem.h | 5 +- include/clang/CodeGen/BackendUtil.h | 10 +- include/clang/Driver/Action.h | 67 +-- include/clang/Driver/Compilation.h | 16 +- include/clang/Driver/Driver.h | 26 +- include/clang/Driver/Options.td | 8 +- include/clang/Driver/ToolChain.h | 2 +- include/clang/Lex/LiteralSupport.h | 1 + include/clang/Parse/Parser.h | 30 +- include/clang/Sema/DeclSpec.h | 32 +- include/clang/Sema/Lookup.h | 1 + include/clang/Sema/Overload.h | 9 +- include/clang/Sema/Sema.h | 12 +- include/clang/Serialization/ASTBitCodes.h | 4 +- include/clang/Serialization/ASTWriter.h | 1 + .../StaticAnalyzer/Core/PathSensitive/MemRegion.h | 117 ++-- .../Core/PathSensitive/SValBuilder.h | 6 +- .../StaticAnalyzer/Core/PathSensitive/SVals.h | 28 +- .../Core/PathSensitive/SymbolManager.h | 84 +-- lib/AST/ASTContext.cpp | 53 ++ lib/AST/ASTDumper.cpp | 4 + lib/AST/ASTImporter.cpp | 8 + lib/AST/Decl.cpp | 16 +- lib/AST/DeclBase.cpp | 7 +- lib/AST/Expr.cpp | 3 + lib/AST/ExprCXX.cpp | 8 - lib/AST/ExprConstant.cpp | 7 +- lib/AST/ItaniumMangle.cpp | 8 + lib/AST/MicrosoftMangle.cpp | 9 + lib/AST/RecordLayoutBuilder.cpp | 10 +- lib/AST/StmtPrinter.cpp | 1 + lib/AST/Type.cpp | 7 +- lib/AST/TypePrinter.cpp | 10 + lib/Basic/Targets.cpp | 23 +- lib/Basic/VirtualFileSystem.cpp | 17 + lib/CodeGen/BackendUtil.cpp | 49 +- lib/CodeGen/CGDebugInfo.cpp | 8 + lib/CodeGen/CGDebugInfo.h | 1 + lib/CodeGen/CGExpr.cpp | 1 + lib/CodeGen/CGExprAgg.cpp | 1 + lib/CodeGen/CGExprComplex.cpp | 1 + lib/CodeGen/CGExprConstant.cpp | 1 + lib/CodeGen/CGExprScalar.cpp | 25 +- lib/CodeGen/CGOpenCLRuntime.cpp | 11 + lib/CodeGen/CGOpenCLRuntime.h | 5 +- lib/CodeGen/CGOpenMPRuntime.cpp | 2 +- lib/CodeGen/CGOpenMPRuntime.h | 4 +- lib/CodeGen/CodeGenAction.cpp | 36 +- lib/CodeGen/CodeGenFunction.cpp | 31 +- lib/CodeGen/CodeGenModule.cpp | 15 +- lib/CodeGen/CodeGenPGO.cpp | 2 +- lib/CodeGen/CodeGenTypes.cpp | 4 + lib/CodeGen/CoverageMappingGen.cpp | 20 +- lib/CodeGen/CoverageMappingGen.h | 4 +- lib/CodeGen/ItaniumCXXABI.cpp | 6 + lib/CodeGen/ObjectFilePCHContainerOperations.cpp | 19 +- lib/Driver/Action.cpp | 117 ++-- lib/Driver/Compilation.cpp | 8 +- lib/Driver/Driver.cpp | 214 ++++---- lib/Driver/InputInfo.h | 33 +- lib/Driver/MSVCToolChain.cpp | 171 +++--- lib/Driver/MinGWToolChain.cpp | 16 +- lib/Driver/ToolChains.cpp | 11 +- lib/Driver/ToolChains.h | 3 - lib/Driver/Tools.cpp | 57 +- lib/Driver/Tools.h | 4 +- lib/Edit/RewriteObjCFoundationAPI.cpp | 3 + lib/Format/ContinuationIndenter.cpp | 28 +- lib/Format/Format.cpp | 8 +- lib/Format/TokenAnnotator.cpp | 29 +- lib/Format/UnwrappedLineParser.cpp | 135 +++-- lib/Format/UnwrappedLineParser.h | 1 + lib/Format/WhitespaceManager.cpp | 58 +- lib/Format/WhitespaceManager.h | 7 +- lib/Frontend/CompilerInvocation.cpp | 9 +- lib/Frontend/FrontendActions.cpp | 20 +- lib/Frontend/MultiplexConsumer.cpp | 6 + lib/Headers/altivec.h | 38 +- lib/Lex/HeaderSearch.cpp | 3 +- lib/Lex/LiteralSupport.cpp | 1 + lib/Lex/Pragma.cpp | 19 +- lib/Parse/ParseDecl.cpp | 36 ++ lib/Parse/ParseDeclCXX.cpp | 3 +- lib/Parse/ParseOpenMP.cpp | 12 +- lib/Parse/ParsePragma.cpp | 8 + lib/Parse/ParseStmt.cpp | 52 +- lib/Parse/Parser.cpp | 3 + lib/Sema/DeclSpec.cpp | 17 + lib/Sema/SemaCast.cpp | 2 + lib/Sema/SemaChecking.cpp | 19 +- lib/Sema/SemaDecl.cpp | 81 ++- lib/Sema/SemaDeclAttr.cpp | 48 +- lib/Sema/SemaDeclCXX.cpp | 5 + lib/Sema/SemaExpr.cpp | 88 ++- lib/Sema/SemaExprCXX.cpp | 17 +- lib/Sema/SemaExprObjC.cpp | 2 + lib/Sema/SemaLookup.cpp | 19 + lib/Sema/SemaOverload.cpp | 27 +- lib/Sema/SemaTemplate.cpp | 6 + lib/Sema/SemaTemplateDeduction.cpp | 2 + lib/Sema/SemaTemplateVariadic.cpp | 1 + lib/Sema/SemaType.cpp | 58 +- lib/Sema/TreeTransform.h | 39 +- lib/Serialization/ASTCommon.h | 1 + lib/Serialization/ASTReader.cpp | 14 + lib/Serialization/ASTReaderDecl.cpp | 15 + lib/Serialization/ASTReaderStmt.cpp | 16 +- lib/Serialization/ASTWriter.cpp | 23 + lib/Serialization/ASTWriterDecl.cpp | 2 +- lib/Serialization/ASTWriterStmt.cpp | 7 - lib/StaticAnalyzer/Checkers/CStringChecker.cpp | 6 +- lib/StaticAnalyzer/Checkers/MallocChecker.cpp | 6 +- lib/StaticAnalyzer/Core/ExprEngineC.cpp | 13 +- lib/StaticAnalyzer/Core/MemRegion.cpp | 60 +- lib/StaticAnalyzer/Core/ProgramState.cpp | 18 +- lib/StaticAnalyzer/Core/RangeConstraintManager.cpp | 4 +- lib/StaticAnalyzer/Core/SValBuilder.cpp | 45 +- lib/StaticAnalyzer/Core/SVals.cpp | 8 +- lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp | 8 +- lib/StaticAnalyzer/Core/Store.cpp | 8 +- lib/StaticAnalyzer/Core/SymbolManager.cpp | 36 +- lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp | 9 +- test/Analysis/inlining/analysis-order.c | 15 + test/Analysis/range_casts.c | 156 ++++++ test/CXX/class/class.mem/p13.cpp | 4 +- test/CXX/class/class.union/class.union.anon/p1.cpp | 24 + test/CXX/class/class.union/class.union.anon/p4.cpp | 10 + test/CXX/class/class.union/p8.cpp | 10 - test/CXX/temp/temp.res/temp.local/p6.cpp | 67 ++- test/CodeGen/builtins-ppc-vsx.c | 47 ++ test/CodeGen/target-data.c | 4 +- test/CodeGenCXX/builtins-systemz-zvector.cpp | 50 ++ test/CodeGenCXX/mangle-ms.cpp | 25 + test/CodeGenCXX/pass-object-size.cpp | 18 + test/CodeGenCXX/vector-splat-conversion.cpp | 54 +- test/CodeGenOpenCL/bool_cast.cl | 6 + test/CodeGenOpenCL/pipe_types.cl | 27 + test/Driver/amdgpu-toolchain.c | 2 +- test/Driver/appletvos-version-min.c | 1 + test/Driver/arm-xscale.c | 3 + test/Driver/cl-options.c | 9 +- test/Driver/cuda-bad-arch.cu | 22 + test/Driver/cuda-options.cu | 289 ++++------ test/Driver/cuda-unused-arg-warning.cu | 23 + test/Driver/debug-options.c | 2 +- test/Driver/fortran.f95 | 6 + test/Driver/gcc_forward.c | 13 +- test/Driver/pic.c | 2 + test/Driver/wasm-toolchain.c | 47 +- test/Driver/wasm32-unknown-unknown.cpp | 20 +- test/Driver/wasm64-unknown-unknown.cpp | 20 +- test/Index/print-type-declaration.cpp | 12 + test/Misc/ast-dump-lookups.cpp | 21 +- test/Misc/ast-print-char-literal.cpp | 24 + test/Modules/Inputs/DebugCXX.h | 10 +- test/Modules/Inputs/dummy.h | 4 +- test/Modules/Inputs/using-decl-redecl/a.h | 3 +- test/Modules/Inputs/using-decl-redecl/d.h | 1 + .../Inputs/using-decl-redecl/module.modulemap | 5 +- test/Modules/ModuleDebugInfo.cpp | 18 +- test/Modules/modular_maps.cpp | 2 +- test/Modules/separate_map_tree.cpp | 2 +- test/Modules/tag-injection.c | 18 + test/Modules/tag-injection.cpp | 7 +- test/Modules/using-decl-redecl.cpp | 12 +- test/OpenMP/barrier_ast_print.cpp | 36 ++ test/OpenMP/barrier_messages.cpp | 8 +- test/OpenMP/cancel_messages.cpp | 4 +- test/OpenMP/cancellation_point_messages.cpp | 4 +- test/OpenMP/flush_messages.cpp | 8 +- test/OpenMP/target_codegen_registration.cpp | 48 +- test/OpenMP/target_codegen_registration_naming.cpp | 8 +- test/OpenMP/taskwait_messages.cpp | 8 +- test/OpenMP/taskyield_messages.cpp | 8 +- test/OpenMP/threadprivate_messages.cpp | 3 + test/PCH/chain-default-argument-instantiation.cpp | 50 ++ test/PCH/cxx-char-literal.cpp | 19 + test/PCH/ocl_types.cl | 18 +- test/PCH/ocl_types.h | 11 + test/Sema/bitfield-layout.c | 186 ++++++- test/Sema/darwin-tls.c | 17 + test/Sema/decl-in-prototype.c | 3 + test/Sema/integer-overflow.c | 8 + test/Sema/pass-object-size.c | 6 +- test/SemaCUDA/Inputs/cuda.h | 4 + test/SemaCUDA/attributes-on-non-cuda.cu | 34 ++ test/SemaCUDA/attributes.cu | 33 -- test/SemaCUDA/bad-attributes.cu | 49 ++ test/SemaCXX/anonymous-union.cpp | 4 +- test/SemaCXX/conversion.cpp | 127 ++++- test/SemaCXX/linkage-invalid-decl.cpp | 9 + test/SemaCXX/pass-object-size.cpp | 14 + test/SemaOpenCL/invalid-pipes-cl2.0.cl | 8 + test/SemaOpenCL/pipes-1.2-negative.cl | 3 + test/SemaTemplate/default-arguments-cxx0x.cpp | 19 + test/SemaTemplate/temp_arg_template.cpp | 12 +- tools/CMakeLists.txt | 4 +- tools/c-index-test/c-index-test.c | 20 + tools/libclang/CIndex.cpp | 4 + tools/libclang/CXType.cpp | 6 + tools/scan-build-py/README.md | 120 ++++ tools/scan-build-py/bin/analyze-build | 17 + tools/scan-build-py/bin/analyze-c++ | 14 + tools/scan-build-py/bin/analyze-cc | 14 + tools/scan-build-py/bin/intercept-build | 17 + tools/scan-build-py/bin/intercept-c++ | 14 + tools/scan-build-py/bin/intercept-cc | 14 + tools/scan-build-py/bin/scan-build | 17 + tools/scan-build-py/libear/__init__.py | 260 +++++++++ tools/scan-build-py/libear/config.h.in | 23 + tools/scan-build-py/libear/ear.c | 605 +++++++++++++++++++++ tools/scan-build-py/libscanbuild/__init__.py | 82 +++ tools/scan-build-py/libscanbuild/analyze.py | 502 +++++++++++++++++ tools/scan-build-py/libscanbuild/clang.py | 156 ++++++ tools/scan-build-py/libscanbuild/command.py | 133 +++++ tools/scan-build-py/libscanbuild/intercept.py | 359 ++++++++++++ tools/scan-build-py/libscanbuild/report.py | 530 ++++++++++++++++++ .../libscanbuild/resources/scanview.css | 62 +++ .../libscanbuild/resources/selectable.js | 47 ++ .../libscanbuild/resources/sorttable.js | 492 +++++++++++++++++ tools/scan-build-py/libscanbuild/runner.py | 256 +++++++++ tools/scan-build-py/libscanbuild/shell.py | 66 +++ tools/scan-build-py/tests/__init__.py | 18 + tools/scan-build-py/tests/functional/__init__.py | 0 .../tests/functional/cases/__init__.py | 71 +++ .../tests/functional/cases/test_create_cdb.py | 191 +++++++ .../tests/functional/cases/test_exec_anatomy.py | 50 ++ .../tests/functional/cases/test_from_cdb.py | 183 +++++++ .../tests/functional/cases/test_from_cmd.py | 118 ++++ .../tests/functional/exec/CMakeLists.txt | 32 ++ .../tests/functional/exec/config.h.in | 20 + tools/scan-build-py/tests/functional/exec/main.c | 307 +++++++++++ .../tests/functional/src/broken-one.c | 6 + .../tests/functional/src/broken-two.c | 1 + .../tests/functional/src/build/Makefile | 42 ++ .../scan-build-py/tests/functional/src/clean-one.c | 13 + .../scan-build-py/tests/functional/src/clean-two.c | 11 + .../src/compilation_database/build_broken.json.in | 43 ++ .../src/compilation_database/build_clean.json.in | 19 + .../src/compilation_database/build_regular.json.in | 31 ++ .../scan-build-py/tests/functional/src/emit-one.c | 23 + .../scan-build-py/tests/functional/src/emit-two.c | 13 + .../tests/functional/src/include/clean-one.h | 6 + tools/scan-build-py/tests/functional/src/main.c | 4 + tools/scan-build-py/tests/unit/__init__.py | 24 + tools/scan-build-py/tests/unit/fixtures.py | 40 ++ tools/scan-build-py/tests/unit/test_analyze.py | 8 + tools/scan-build-py/tests/unit/test_clang.py | 41 ++ tools/scan-build-py/tests/unit/test_command.py | 193 +++++++ tools/scan-build-py/tests/unit/test_intercept.py | 123 +++++ tools/scan-build-py/tests/unit/test_report.py | 146 +++++ tools/scan-build-py/tests/unit/test_runner.py | 213 ++++++++ tools/scan-build-py/tests/unit/test_shell.py | 42 ++ unittests/AST/SourceLocationTest.cpp | 38 ++ unittests/Basic/VirtualFileSystemTest.cpp | 75 +-- unittests/Format/FormatTest.cpp | 51 +- unittests/Format/FormatTestJS.cpp | 61 ++- unittests/Format/FormatTestSelective.cpp | 7 + 279 files changed, 9523 insertions(+), 1371 deletions(-) create mode 100644 test/Analysis/inlining/analysis-order.c create mode 100644 test/Analysis/range_casts.c create mode 100644 test/CXX/class/class.union/class.union.anon/p1.cpp create mode 100644 test/CXX/class/class.union/class.union.anon/p4.cpp delete mode 100644 test/CXX/class/class.union/p8.cpp create mode 100644 test/CodeGenCXX/builtins-systemz-zvector.cpp create mode 100644 test/CodeGenOpenCL/pipe_types.cl create mode 100644 test/Driver/arm-xscale.c create mode 100644 test/Driver/cuda-bad-arch.cu create mode 100644 test/Driver/cuda-unused-arg-warning.cu create mode 100644 test/Index/print-type-declaration.cpp create mode 100644 test/Misc/ast-print-char-literal.cpp create mode 100644 test/Modules/Inputs/using-decl-redecl/d.h create mode 100644 test/Modules/tag-injection.c create mode 100644 test/PCH/chain-default-argument-instantiation.cpp create mode 100644 test/PCH/cxx-char-literal.cpp create mode 100644 test/Sema/darwin-tls.c create mode 100644 test/SemaCUDA/attributes-on-non-cuda.cu delete mode 100644 test/SemaCUDA/attributes.cu create mode 100644 test/SemaCUDA/bad-attributes.cu create mode 100644 test/SemaCXX/linkage-invalid-decl.cpp create mode 100644 test/SemaOpenCL/invalid-pipes-cl2.0.cl create mode 100644 test/SemaOpenCL/pipes-1.2-negative.cl create mode 100644 tools/scan-build-py/README.md create mode 100644 tools/scan-build-py/bin/analyze-build create mode 100644 tools/scan-build-py/bin/analyze-c++ create mode 100644 tools/scan-build-py/bin/analyze-cc create mode 100644 tools/scan-build-py/bin/intercept-build create mode 100644 tools/scan-build-py/bin/intercept-c++ create mode 100644 tools/scan-build-py/bin/intercept-cc create mode 100644 tools/scan-build-py/bin/scan-build create mode 100644 tools/scan-build-py/libear/__init__.py create mode 100644 tools/scan-build-py/libear/config.h.in create mode 100644 tools/scan-build-py/libear/ear.c create mode 100644 tools/scan-build-py/libscanbuild/__init__.py create mode 100644 tools/scan-build-py/libscanbuild/analyze.py create mode 100644 tools/scan-build-py/libscanbuild/clang.py create mode 100644 tools/scan-build-py/libscanbuild/command.py create mode 100644 tools/scan-build-py/libscanbuild/intercept.py create mode 100644 tools/scan-build-py/libscanbuild/report.py create mode 100644 tools/scan-build-py/libscanbuild/resources/scanview.css create mode 100644 tools/scan-build-py/libscanbuild/resources/selectable.js create mode 100644 tools/scan-build-py/libscanbuild/resources/sorttable.js create mode 100644 tools/scan-build-py/libscanbuild/runner.py create mode 100644 tools/scan-build-py/libscanbuild/shell.py create mode 100644 tools/scan-build-py/tests/__init__.py create mode 100644 tools/scan-build-py/tests/functional/__init__.py create mode 100644 tools/scan-build-py/tests/functional/cases/__init__.py create mode 100644 tools/scan-build-py/tests/functional/cases/test_create_cdb.py create mode 100644 tools/scan-build-py/tests/functional/cases/test_exec_anatomy.py create mode 100644 tools/scan-build-py/tests/functional/cases/test_from_cdb.py create mode 100644 tools/scan-build-py/tests/functional/cases/test_from_cmd.py create mode 100644 tools/scan-build-py/tests/functional/exec/CMakeLists.txt create mode 100644 tools/scan-build-py/tests/functional/exec/config.h.in create mode 100644 tools/scan-build-py/tests/functional/exec/main.c create mode 100644 tools/scan-build-py/tests/functional/src/broken-one.c create mode 100644 tools/scan-build-py/tests/functional/src/broken-two.c create mode 100644 tools/scan-build-py/tests/functional/src/build/Makefile create mode 100644 tools/scan-build-py/tests/functional/src/clean-one.c create mode 100644 tools/scan-build-py/tests/functional/src/clean-two.c create mode 100644 tools/scan-build-py/tests/functional/src/compilation_database/build_broken.json.in create mode 100644 tools/scan-build-py/tests/functional/src/compilation_database/build_clean.json.in create mode 100644 tools/scan-build-py/tests/functional/src/compilation_database/build_regular.json.in create mode 100644 tools/scan-build-py/tests/functional/src/emit-one.c create mode 100644 tools/scan-build-py/tests/functional/src/emit-two.c create mode 100644 tools/scan-build-py/tests/functional/src/include/clean-one.h create mode 100644 tools/scan-build-py/tests/functional/src/main.c create mode 100644 tools/scan-build-py/tests/unit/__init__.py create mode 100644 tools/scan-build-py/tests/unit/fixtures.py create mode 100644 tools/scan-build-py/tests/unit/test_analyze.py create mode 100644 tools/scan-build-py/tests/unit/test_clang.py create mode 100644 tools/scan-build-py/tests/unit/test_command.py create mode 100644 tools/scan-build-py/tests/unit/test_intercept.py create mode 100644 tools/scan-build-py/tests/unit/test_report.py create mode 100644 tools/scan-build-py/tests/unit/test_runner.py create mode 100644 tools/scan-build-py/tests/unit/test_shell.py diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index b66009e909a1..abf92948bb42 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -131,6 +131,7 @@ class ASTContext : public RefCountedBase { mutable llvm::FoldingSet AutoTypes; mutable llvm::FoldingSet AtomicTypes; llvm::FoldingSet AttributedTypes; + mutable llvm::FoldingSet PipeTypes; mutable llvm::FoldingSet QualifiedTemplateNames; mutable llvm::FoldingSet DependentTemplateNames; @@ -1079,6 +1080,9 @@ public: /// blocks. QualType getBlockDescriptorType() const; + /// \brief Return pipe type for the specified type. + QualType getPipeType(QualType T) const; + /// Gets the struct used to keep track of the extended descriptor for /// pointer to blocks. QualType getBlockDescriptorExtendedType() const; @@ -2279,9 +2283,13 @@ public: /// \brief Make an APSInt of the appropriate width and signedness for the /// given \p Value and integer \p Type. llvm::APSInt MakeIntValue(uint64_t Value, QualType Type) const { - llvm::APSInt Res(getIntWidth(Type), - !Type->isSignedIntegerOrEnumerationType()); + // If Type is a signed integer type larger than 64 bits, we need to be sure + // to sign extend Res appropriately. + llvm::APSInt Res(64, !Type->isSignedIntegerOrEnumerationType()); Res = Value; + unsigned Width = getIntWidth(Type); + if (Width != Res.getBitWidth()) + return Res.extOrTrunc(Width); return Res; } diff --git a/include/clang/AST/ASTMutationListener.h b/include/clang/AST/ASTMutationListener.h index 3ff392de11a7..cf3b55d7b2c7 100644 --- a/include/clang/AST/ASTMutationListener.h +++ b/include/clang/AST/ASTMutationListener.h @@ -29,6 +29,7 @@ namespace clang { class ObjCContainerDecl; class ObjCInterfaceDecl; class ObjCPropertyDecl; + class ParmVarDecl; class QualType; class RecordDecl; class TagDecl; @@ -88,6 +89,9 @@ public: /// \brief A function template's definition was instantiated. virtual void FunctionDefinitionInstantiated(const FunctionDecl *D) {} + /// \brief A default argument was instantiated. + virtual void DefaultArgumentInstantiated(const ParmVarDecl *D) {} + /// \brief A new objc category class was added for an interface. virtual void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD, const ObjCInterfaceDecl *IFD) {} diff --git a/include/clang/AST/BuiltinTypes.def b/include/clang/AST/BuiltinTypes.def index 85e237a2bf04..a08a6839024b 100644 --- a/include/clang/AST/BuiltinTypes.def +++ b/include/clang/AST/BuiltinTypes.def @@ -1,4 +1,4 @@ -//===-- BuiltinTypeNodes.def - Metadata about BuiltinTypes ------*- C++ -*-===// +//===-- BuiltinTypes.def - Metadata about BuiltinTypes ----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 046ce70a343b..029c1182f26e 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -2440,10 +2440,9 @@ class IndirectFieldDecl : public ValueDecl, NamedDecl **Chaining; unsigned ChainingSize; - IndirectFieldDecl(DeclContext *DC, SourceLocation L, + IndirectFieldDecl(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName N, QualType T, - NamedDecl **CH, unsigned CHS) - : ValueDecl(IndirectField, DC, L, N, T), Chaining(CH), ChainingSize(CHS) {} + NamedDecl **CH, unsigned CHS); public: static IndirectFieldDecl *Create(ASTContext &C, DeclContext *DC, diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index 05b2a1280fab..2d6e84a68aa5 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -113,6 +113,9 @@ public: /// Tags, declared with 'struct foo;' and referenced with /// 'struct foo'. All tags are also types. This is what /// elaborated-type-specifiers look for in C. + /// This also contains names that conflict with tags in the + /// same scope but that are otherwise ordinary names (non-type + /// template parameters and indirect field declarations). IDNS_Tag = 0x0002, /// Types, declared with 'struct foo', typedefs, etc. @@ -131,7 +134,7 @@ public: IDNS_Namespace = 0x0010, /// Ordinary names. In C, everything that's not a label, tag, - /// or member ends up here. + /// member, or function-local extern ends up here. IDNS_Ordinary = 0x0020, /// Objective C \@protocol. @@ -160,7 +163,9 @@ public: /// This declaration is a function-local extern declaration of a /// variable or function. This may also be IDNS_Ordinary if it - /// has been declared outside any function. + /// has been declared outside any function. These act mostly like + /// invisible friend declarations, but are also visible to unqualified + /// lookup within the scope of the declaring function. IDNS_LocalExtern = 0x0800 }; diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 095dd6a1ef34..38733eee82c3 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -1292,6 +1292,7 @@ public: enum CharacterKind { Ascii, Wide, + UTF8, UTF16, UTF32 }; diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 0608abac1fe9..682127498647 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -951,15 +951,9 @@ public: /// This wraps up a function call argument that was created from the /// corresponding parameter's default argument, when the call did not /// explicitly supply arguments for all of the parameters. -class CXXDefaultArgExpr final - : public Expr, - private llvm::TrailingObjects { +class CXXDefaultArgExpr final : public Expr { /// \brief The parameter whose default is being used. - /// - /// When the bit is set, the subexpression is stored after the - /// CXXDefaultArgExpr itself. When the bit is clear, the parameter's - /// actual default expression is the subexpression. - llvm::PointerIntPair Param; + ParmVarDecl *Param; /// \brief The location where the default argument expression was used. SourceLocation Loc; @@ -971,16 +965,7 @@ class CXXDefaultArgExpr final : param->getDefaultArg()->getType(), param->getDefaultArg()->getValueKind(), param->getDefaultArg()->getObjectKind(), false, false, false, false), - Param(param, false), Loc(Loc) { } - - CXXDefaultArgExpr(StmtClass SC, SourceLocation Loc, ParmVarDecl *param, - Expr *SubExpr) - : Expr(SC, SubExpr->getType(), - SubExpr->getValueKind(), SubExpr->getObjectKind(), - false, false, false, false), - Param(param, true), Loc(Loc) { - *getTrailingObjects() = SubExpr; - } + Param(param), Loc(Loc) { } public: CXXDefaultArgExpr(EmptyShell Empty) : Expr(CXXDefaultArgExprClass, Empty) {} @@ -992,24 +977,15 @@ public: return new (C) CXXDefaultArgExpr(CXXDefaultArgExprClass, Loc, Param); } - // \p Param is the parameter whose default argument is used by this - // expression, and \p SubExpr is the expression that will actually be used. - static CXXDefaultArgExpr *Create(const ASTContext &C, SourceLocation Loc, - ParmVarDecl *Param, Expr *SubExpr); - // Retrieve the parameter that the argument was created from. - const ParmVarDecl *getParam() const { return Param.getPointer(); } - ParmVarDecl *getParam() { return Param.getPointer(); } + const ParmVarDecl *getParam() const { return Param; } + ParmVarDecl *getParam() { return Param; } // Retrieve the actual argument to the function call. const Expr *getExpr() const { - if (Param.getInt()) - return *getTrailingObjects(); return getParam()->getDefaultArg(); } Expr *getExpr() { - if (Param.getInt()) - return *getTrailingObjects(); return getParam()->getDefaultArg(); } @@ -1033,7 +1009,6 @@ public: return child_range(child_iterator(), child_iterator()); } - friend TrailingObjects; friend class ASTStmtReader; friend class ASTStmtWriter; }; diff --git a/include/clang/AST/OperationKinds.h b/include/clang/AST/OperationKinds.h index 2235c1012fb7..102bbc21edb3 100644 --- a/include/clang/AST/OperationKinds.h +++ b/include/clang/AST/OperationKinds.h @@ -185,7 +185,11 @@ enum CastKind { /// CK_FloatingToBoolean - Floating point to boolean. /// (bool) f CK_FloatingToBoolean, - + + // CK_BooleanToSignedIntegral - Convert a boolean to -1 or 0 for true and + // false, respectively. + CK_BooleanToSignedIntegral, + /// CK_FloatingCast - Casting between floating types of different size. /// (double) f /// (float) ld diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index e6f758364a85..0c25a45c1cec 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -978,6 +978,8 @@ DEF_TRAVERSE_TYPE(ObjCObjectPointerType, DEF_TRAVERSE_TYPE(AtomicType, { TRY_TO(TraverseType(T->getValueType())); }) +DEF_TRAVERSE_TYPE(PipeType, { TRY_TO(TraverseType(T->getElementType())); }) + #undef DEF_TRAVERSE_TYPE // ----------------- TypeLoc traversal ----------------- @@ -1206,6 +1208,8 @@ DEF_TRAVERSE_TYPELOC(ObjCObjectPointerType, DEF_TRAVERSE_TYPELOC(AtomicType, { TRY_TO(TraverseTypeLoc(TL.getValueLoc())); }) +DEF_TRAVERSE_TYPELOC(PipeType, { TRY_TO(TraverseTypeLoc(TL.getValueLoc())); }) + #undef DEF_TRAVERSE_TYPELOC // ----------------- Decl traversal ----------------- diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index e48b7dcc28f5..d3950e92cf0d 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -130,7 +130,7 @@ protected: friend class CharacterLiteral; unsigned : NumExprBits; - unsigned Kind : 2; + unsigned Kind : 3; }; enum APFloatSemantics { diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 0c08130da621..d63b2c43d553 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -1721,6 +1721,7 @@ public: bool isNDRangeT() const; // OpenCL ndrange_t bool isReserveIDT() const; // OpenCL reserve_id_t + bool isPipeType() const; // OpenCL pipe type bool isOpenCLSpecificType() const; // Any OpenCL specific type /// Determines if this type, which must satisfy @@ -5015,6 +5016,41 @@ class AtomicType : public Type, public llvm::FoldingSetNode { } }; +/// PipeType - OpenCL20. +class PipeType : public Type, public llvm::FoldingSetNode { + QualType ElementType; + + PipeType(QualType elemType, QualType CanonicalPtr) : + Type(Pipe, CanonicalPtr, elemType->isDependentType(), + elemType->isInstantiationDependentType(), + elemType->isVariablyModifiedType(), + elemType->containsUnexpandedParameterPack()), + ElementType(elemType) {} + friend class ASTContext; // ASTContext creates these. + +public: + + QualType getElementType() const { return ElementType; } + + bool isSugared() const { return false; } + + QualType desugar() const { return QualType(this, 0); } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getElementType()); + } + + static void Profile(llvm::FoldingSetNodeID &ID, QualType T) { + ID.AddPointer(T.getAsOpaquePtr()); + } + + + static bool classof(const Type *T) { + return T->getTypeClass() == Pipe; + } + +}; + /// A qualifier set is used to build a set of qualifiers. class QualifierCollector : public Qualifiers { public: @@ -5461,9 +5497,13 @@ inline bool Type::isImageType() const { isImage1dBufferT(); } +inline bool Type::isPipeType() const { + return isa(CanonicalType); +} + inline bool Type::isOpenCLSpecificType() const { return isSamplerT() || isEventT() || isImageType() || isClkEventT() || - isQueueT() || isNDRangeT() || isReserveIDT(); + isQueueT() || isNDRangeT() || isReserveIDT() || isPipeType(); } inline bool Type::isTemplateTypeParmType() const { diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index 26feda5d7668..29035a41776e 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -2033,7 +2033,26 @@ public: } }; +struct PipeTypeLocInfo { + SourceLocation KWLoc; +}; + +class PipeTypeLoc : public ConcreteTypeLoc { +public: + TypeLoc getValueLoc() const { return this->getInnerTypeLoc(); } + + SourceRange getLocalSourceRange() const { return SourceRange(getKWLoc()); } + + SourceLocation getKWLoc() const { return this->getLocalData()->KWLoc; } + void setKWLoc(SourceLocation Loc) { this->getLocalData()->KWLoc = Loc; } + void initializeLocal(ASTContext &Context, SourceLocation Loc) { + setKWLoc(Loc); + } + + QualType getInnerType() const { return this->getTypePtr()->getElementType(); } +}; } #endif diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def index 2549f0bf50c5..8caf1024142d 100644 --- a/include/clang/AST/TypeNodes.def +++ b/include/clang/AST/TypeNodes.def @@ -104,6 +104,7 @@ NON_CANONICAL_UNLESS_DEPENDENT_TYPE(PackExpansion, Type) TYPE(ObjCObject, Type) TYPE(ObjCInterface, ObjCObjectType) TYPE(ObjCObjectPointer, Type) +TYPE(Pipe, Type) TYPE(Atomic, Type) #ifdef LAST_TYPE diff --git a/include/clang/ASTMatchers/ASTMatchersInternal.h b/include/clang/ASTMatchers/ASTMatchersInternal.h index d49909183fd4..1d1d7952c166 100644 --- a/include/clang/ASTMatchers/ASTMatchersInternal.h +++ b/include/clang/ASTMatchers/ASTMatchersInternal.h @@ -560,10 +560,10 @@ bool matchesFirstInPointerRange(const MatcherT &Matcher, IteratorT Start, // Metafunction to determine if type T has a member called // getDecl. -#if defined(_MSC_VER) && (_MSC_VER < 1900) && !defined(__clang__) -// For old versions of MSVC, we use a weird nonstandard __if_exists -// statement, since before MSVC2015, it was not standards-conformant -// enough to compile the usual code below. +#if defined(_MSC_VER) && !defined(__clang__) +// For MSVC, we use a weird nonstandard __if_exists statement, as it +// is not standards-conformant enough to properly compile the standard +// code below. (At least up through MSVC 2015 require this workaround) template struct has_getDecl { __if_exists(T::getDecl) { enum { value = 1 }; diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td index ce270bfffc69..b04498f3188c 100644 --- a/include/clang/Basic/DiagnosticDriverKinds.td +++ b/include/clang/Basic/DiagnosticDriverKinds.td @@ -22,6 +22,7 @@ def err_drv_unknown_stdin_type_clang_cl : Error< def err_drv_unknown_language : Error<"language not recognized: '%0'">; def err_drv_invalid_arch_name : Error< "invalid arch name '%0'">; +def err_drv_cuda_bad_gpu_arch : Error<"Unsupported CUDA gpu architecture: %0">; def err_drv_invalid_thread_model_for_target : Error< "invalid thread model '%0' in '%1' for this target">; def err_drv_invalid_linker_name : Error< diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 8e5f57d6d890..2e4e57b63b8e 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -616,6 +616,7 @@ def Most : DiagGroup<"most", [ CharSubscript, Comment, DeleteNonVirtualDtor, + ForLoopAnalysis, Format, Implicit, InfiniteRecursion, diff --git a/include/clang/Basic/DiagnosticIDs.h b/include/clang/Basic/DiagnosticIDs.h index a675dfabe46d..312b71f4064d 100644 --- a/include/clang/Basic/DiagnosticIDs.h +++ b/include/clang/Basic/DiagnosticIDs.h @@ -29,7 +29,7 @@ namespace clang { enum { DIAG_START_COMMON = 0, DIAG_START_DRIVER = DIAG_START_COMMON + 300, - DIAG_START_FRONTEND = DIAG_START_DRIVER + 100, + DIAG_START_FRONTEND = DIAG_START_DRIVER + 200, DIAG_START_SERIALIZATION = DIAG_START_FRONTEND + 100, DIAG_START_LEX = DIAG_START_SERIALIZATION + 120, DIAG_START_PARSE = DIAG_START_LEX + 300, diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td index ed6ff20f5c42..2fc9664f49e5 100644 --- a/include/clang/Basic/DiagnosticLexKinds.td +++ b/include/clang/Basic/DiagnosticLexKinds.td @@ -490,6 +490,8 @@ def warn_pragma_diagnostic_unknown_warning : // - #pragma __debug def warn_pragma_debug_unexpected_command : Warning< "unexpected debug command '%0'">, InGroup; +def warn_pragma_debug_missing_argument : Warning< + "missing argument to debug command '%0'">, InGroup; def err_defined_macro_name : Error<"'defined' cannot be used as a macro name">; def err_paste_at_start : Error< diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 59f5095d6467..6ba482c78e4a 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1,4 +1,3 @@ - //==--- DiagnosticSemaKinds.td - libsema diagnostics ----------------------===// // // The LLVM Compiler Infrastructure @@ -7643,6 +7642,10 @@ def err_wrong_sampler_addressspace: Error< "sampler type cannot be used with the __local and __global address space qualifiers">; def err_opencl_global_invalid_addr_space : Error< "program scope variable must reside in %0 address space">; +def err_missing_actual_pipe_type : Error< + "missing actual type specifier for pipe">; +def err_reference_pipe_type : Error < + "pipes packet types cannot be of reference type">; def err_opencl_no_main : Error<"%select{function|kernel}0 cannot be called 'main'">; def err_opencl_kernel_attr : Error<"attribute %0 can only be applied to a kernel function">; diff --git a/include/clang/Basic/Specifiers.h b/include/clang/Basic/Specifiers.h index 1d59d64d6bc7..e284171f7773 100644 --- a/include/clang/Basic/Specifiers.h +++ b/include/clang/Basic/Specifiers.h @@ -36,6 +36,11 @@ namespace clang { TSS_unsigned }; + enum TypeSpecifiersPipe { + TSP_unspecified, + TSP_pipe + }; + /// \brief Specifies the kind of type. enum TypeSpecifierType { TST_unspecified, diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def index 9252d9947a94..026945141d24 100644 --- a/include/clang/Basic/TokenKinds.def +++ b/include/clang/Basic/TokenKinds.def @@ -519,6 +519,8 @@ KEYWORD(vec_step , KEYOPENCL|KEYALTIVEC|KEYZVECTOR) // OpenMP Type Traits KEYWORD(__builtin_omp_required_simd_align, KEYALL) +KEYWORD(pipe , KEYOPENCL) + // Borland Extensions. KEYWORD(__pascal , KEYALL) @@ -697,6 +699,11 @@ ANNOTATION(pragma_parser_crash) // handles them. ANNOTATION(pragma_captured) +// Annotation for #pragma clang __debug dump... +// The lexer produces these so that the parser and semantic analysis can +// look up and dump the operand. +ANNOTATION(pragma_dump) + // Annotation for #pragma ms_struct... // The lexer produces these so that they only take effect when the parser // handles them. diff --git a/include/clang/Basic/VirtualFileSystem.h b/include/clang/Basic/VirtualFileSystem.h index 1df4947dd7e8..bab88c90b0a8 100644 --- a/include/clang/Basic/VirtualFileSystem.h +++ b/include/clang/Basic/VirtualFileSystem.h @@ -299,10 +299,7 @@ public: llvm::ErrorOr getCurrentWorkingDirectory() const override { return WorkingDirectory; } - std::error_code setCurrentWorkingDirectory(const Twine &Path) override { - WorkingDirectory = Path.str(); - return std::error_code(); - } + std::error_code setCurrentWorkingDirectory(const Twine &Path) override; }; /// \brief Get a globally unique ID for a virtual file or directory. diff --git a/include/clang/CodeGen/BackendUtil.h b/include/clang/CodeGen/BackendUtil.h index ba5dc3939ced..d375a7881313 100644 --- a/include/clang/CodeGen/BackendUtil.h +++ b/include/clang/CodeGen/BackendUtil.h @@ -33,12 +33,10 @@ namespace clang { Backend_EmitObj ///< Emit native object files }; - void - EmitBackendOutput(DiagnosticsEngine &Diags, const CodeGenOptions &CGOpts, - const TargetOptions &TOpts, const LangOptions &LOpts, - StringRef TDesc, llvm::Module *M, BackendAction Action, - raw_pwrite_stream *OS, - std::unique_ptr Index = nullptr); + void EmitBackendOutput(DiagnosticsEngine &Diags, const CodeGenOptions &CGOpts, + const TargetOptions &TOpts, const LangOptions &LOpts, + StringRef TDesc, llvm::Module *M, BackendAction Action, + raw_pwrite_stream *OS); } #endif diff --git a/include/clang/Driver/Action.h b/include/clang/Driver/Action.h index fc31d4b0dec2..c5b0f4755092 100644 --- a/include/clang/Driver/Action.h +++ b/include/clang/Driver/Action.h @@ -15,6 +15,9 @@ #include "llvm/ADT/SmallVector.h" namespace llvm { + +class StringRef; + namespace opt { class Arg; } @@ -32,6 +35,9 @@ namespace driver { /// single primary output, at least in terms of controlling the /// compilation. Actions can produce auxiliary files, but can only /// produce a single output to feed into subsequent actions. +/// +/// Actions are usually owned by a Compilation, which creates new +/// actions via MakeAction(). class Action { public: typedef ActionList::size_type size_type; @@ -70,27 +76,20 @@ private: ActionList Inputs; - unsigned OwnsInputs : 1; - protected: - Action(ActionClass Kind, types::ID Type) - : Kind(Kind), Type(Type), OwnsInputs(true) {} - Action(ActionClass Kind, std::unique_ptr Input, types::ID Type) - : Kind(Kind), Type(Type), Inputs(1, Input.release()), OwnsInputs(true) { - } - Action(ActionClass Kind, std::unique_ptr Input) - : Kind(Kind), Type(Input->getType()), Inputs(1, Input.release()), - OwnsInputs(true) {} + Action(ActionClass Kind, types::ID Type) : Action(Kind, ActionList(), Type) {} + Action(ActionClass Kind, Action *Input, types::ID Type) + : Action(Kind, ActionList({Input}), Type) {} + Action(ActionClass Kind, Action *Input) + : Action(Kind, ActionList({Input}), Input->getType()) {} Action(ActionClass Kind, const ActionList &Inputs, types::ID Type) - : Kind(Kind), Type(Type), Inputs(Inputs), OwnsInputs(true) {} + : Kind(Kind), Type(Type), Inputs(Inputs) {} + public: virtual ~Action(); const char *getClassName() const { return Action::getClassName(getKind()); } - bool getOwnsInputs() { return OwnsInputs; } - void setOwnsInputs(bool Value) { OwnsInputs = Value; } - ActionClass getKind() const { return Kind; } types::ID getType() const { return Type; } @@ -126,7 +125,7 @@ class BindArchAction : public Action { const char *ArchName; public: - BindArchAction(std::unique_ptr Input, const char *ArchName); + BindArchAction(Action *Input, const char *ArchName); const char *getArchName() const { return ArchName; } @@ -137,19 +136,24 @@ public: class CudaDeviceAction : public Action { virtual void anchor(); - /// GPU architecture to bind -- e.g 'sm_35'. + /// GPU architecture to bind. Always of the form /sm_\d+/. const char *GpuArchName; /// True when action results are not consumed by the host action (e.g when /// -fsyntax-only or --cuda-device-only options are used). bool AtTopLevel; public: - CudaDeviceAction(std::unique_ptr Input, const char *ArchName, - bool AtTopLevel); + CudaDeviceAction(Action *Input, const char *ArchName, bool AtTopLevel); const char *getGpuArchName() const { return GpuArchName; } + + /// Gets the compute_XX that corresponds to getGpuArchName(). + const char *getComputeArchName() const; + bool isAtTopLevel() const { return AtTopLevel; } + static bool IsValidGpuArchName(llvm::StringRef ArchName); + static bool classof(const Action *A) { return A->getKind() == CudaDeviceClass; } @@ -160,9 +164,7 @@ class CudaHostAction : public Action { ActionList DeviceActions; public: - CudaHostAction(std::unique_ptr Input, - const ActionList &DeviceActions); - ~CudaHostAction() override; + CudaHostAction(Action *Input, const ActionList &DeviceActions); const ActionList &getDeviceActions() const { return DeviceActions; } @@ -172,7 +174,7 @@ public: class JobAction : public Action { virtual void anchor(); protected: - JobAction(ActionClass Kind, std::unique_ptr Input, types::ID Type); + JobAction(ActionClass Kind, Action *Input, types::ID Type); JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type); public: @@ -185,7 +187,7 @@ public: class PreprocessJobAction : public JobAction { void anchor() override; public: - PreprocessJobAction(std::unique_ptr Input, types::ID OutputType); + PreprocessJobAction(Action *Input, types::ID OutputType); static bool classof(const Action *A) { return A->getKind() == PreprocessJobClass; @@ -195,7 +197,7 @@ public: class PrecompileJobAction : public JobAction { void anchor() override; public: - PrecompileJobAction(std::unique_ptr Input, types::ID OutputType); + PrecompileJobAction(Action *Input, types::ID OutputType); static bool classof(const Action *A) { return A->getKind() == PrecompileJobClass; @@ -205,7 +207,7 @@ public: class AnalyzeJobAction : public JobAction { void anchor() override; public: - AnalyzeJobAction(std::unique_ptr Input, types::ID OutputType); + AnalyzeJobAction(Action *Input, types::ID OutputType); static bool classof(const Action *A) { return A->getKind() == AnalyzeJobClass; @@ -215,7 +217,7 @@ public: class MigrateJobAction : public JobAction { void anchor() override; public: - MigrateJobAction(std::unique_ptr Input, types::ID OutputType); + MigrateJobAction(Action *Input, types::ID OutputType); static bool classof(const Action *A) { return A->getKind() == MigrateJobClass; @@ -225,7 +227,7 @@ public: class CompileJobAction : public JobAction { void anchor() override; public: - CompileJobAction(std::unique_ptr Input, types::ID OutputType); + CompileJobAction(Action *Input, types::ID OutputType); static bool classof(const Action *A) { return A->getKind() == CompileJobClass; @@ -235,7 +237,7 @@ public: class BackendJobAction : public JobAction { void anchor() override; public: - BackendJobAction(std::unique_ptr Input, types::ID OutputType); + BackendJobAction(Action *Input, types::ID OutputType); static bool classof(const Action *A) { return A->getKind() == BackendJobClass; @@ -245,7 +247,7 @@ public: class AssembleJobAction : public JobAction { void anchor() override; public: - AssembleJobAction(std::unique_ptr Input, types::ID OutputType); + AssembleJobAction(Action *Input, types::ID OutputType); static bool classof(const Action *A) { return A->getKind() == AssembleJobClass; @@ -285,8 +287,7 @@ public: class VerifyJobAction : public JobAction { void anchor() override; public: - VerifyJobAction(ActionClass Kind, std::unique_ptr Input, - types::ID Type); + VerifyJobAction(ActionClass Kind, Action *Input, types::ID Type); static bool classof(const Action *A) { return A->getKind() == VerifyDebugInfoJobClass || A->getKind() == VerifyPCHJobClass; @@ -296,7 +297,7 @@ public: class VerifyDebugInfoJobAction : public VerifyJobAction { void anchor() override; public: - VerifyDebugInfoJobAction(std::unique_ptr Input, types::ID Type); + VerifyDebugInfoJobAction(Action *Input, types::ID Type); static bool classof(const Action *A) { return A->getKind() == VerifyDebugInfoJobClass; } @@ -305,7 +306,7 @@ public: class VerifyPCHJobAction : public VerifyJobAction { void anchor() override; public: - VerifyPCHJobAction(std::unique_ptr Input, types::ID Type); + VerifyPCHJobAction(Action *Input, types::ID Type); static bool classof(const Action *A) { return A->getKind() == VerifyPCHJobClass; } diff --git a/include/clang/Driver/Compilation.h b/include/clang/Driver/Compilation.h index 12ff068d133c..3ed19135043a 100644 --- a/include/clang/Driver/Compilation.h +++ b/include/clang/Driver/Compilation.h @@ -48,7 +48,12 @@ class Compilation { /// own argument translation. llvm::opt::DerivedArgList *TranslatedArgs; - /// The list of actions. + /// The list of actions we've created via MakeAction. This is not accessible + /// to consumers; it's here just to manage ownership. + std::vector> AllActions; + + /// The list of actions. This is maintained and modified by consumers, via + /// getActions(). ActionList Actions; /// The root list of jobs. @@ -105,6 +110,15 @@ public: ActionList &getActions() { return Actions; } const ActionList &getActions() const { return Actions; } + /// Creates a new Action owned by this Compilation. + /// + /// The new Action is *not* added to the list returned by getActions(). + template T *MakeAction(Args &&... Arg) { + T *RawPtr = new T(std::forward(Arg)...); + AllActions.push_back(std::unique_ptr(RawPtr)); + return RawPtr; + } + JobList &getJobs() { return Jobs; } const JobList &getJobs() const { return Jobs; } diff --git a/include/clang/Driver/Driver.h b/include/clang/Driver/Driver.h index c9940ba5501f..a229779e1aa1 100644 --- a/include/clang/Driver/Driver.h +++ b/include/clang/Driver/Driver.h @@ -18,10 +18,10 @@ #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" -#include "llvm/Support/Path.h" // FIXME: Kill when CompilationInfo -#include - // lands. +#include "llvm/Support/Path.h" // FIXME: Kill when CompilationInfo lands. + #include +#include #include #include @@ -375,20 +375,16 @@ public: /// ConstructAction - Construct the appropriate action to do for /// \p Phase on the \p Input, taking in to account arguments /// like -fsyntax-only or --analyze. - std::unique_ptr - ConstructPhaseAction(const ToolChain &TC, const llvm::opt::ArgList &Args, - phases::ID Phase, std::unique_ptr Input) const; + Action *ConstructPhaseAction(Compilation &C, const ToolChain &TC, + const llvm::opt::ArgList &Args, phases::ID Phase, + Action *Input) const; /// BuildJobsForAction - Construct the jobs to perform for the - /// action \p A. - void BuildJobsForAction(Compilation &C, - const Action *A, - const ToolChain *TC, - const char *BoundArch, - bool AtTopLevel, - bool MultipleArchs, - const char *LinkingOutput, - InputInfo &Result) const; + /// action \p A and return an InputInfo for the result of running \p A. + InputInfo BuildJobsForAction(Compilation &C, const Action *A, + const ToolChain *TC, const char *BoundArch, + bool AtTopLevel, bool MultipleArchs, + const char *LinkingOutput) const; /// Returns the default name for linked images (e.g., "a.out"). const char *getDefaultImageName() const; diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index e219a9b76b79..e4279e80d847 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -1906,13 +1906,13 @@ def _ : Joined<["--"], "">, Flags<[Unsupported]>; def mieee_rnd_near : Flag<["-"], "mieee-rnd-near">, Group; def mv4 : Flag<["-"], "mv4">, Group, - Alias, AliasArgs<["v4"]>; + Alias, AliasArgs<["hexagonv4"]>; def mv5 : Flag<["-"], "mv5">, Group, Alias, - AliasArgs<["v5"]>; + AliasArgs<["hexagonv5"]>; def mv55 : Flag<["-"], "mv55">, Group, - Alias, AliasArgs<["v55"]>; + Alias, AliasArgs<["hexagonv55"]>; def mv60 : Flag<["-"], "mv60">, Group, - Alias, AliasArgs<["v60"]>; + Alias, AliasArgs<["hexagonv60"]>; def mhexagon_hvx : Flag<["-"], "mhvx">, Group, Flags<[CC1Option]>, HelpText<"Enable Hexagon Vector eXtensions">; def mno_hexagon_hvx : Flag<["-"], "mno-hvx">, Group, diff --git a/include/clang/Driver/ToolChain.h b/include/clang/Driver/ToolChain.h index ed73107940ce..7e68d0a59a09 100644 --- a/include/clang/Driver/ToolChain.h +++ b/include/clang/Driver/ToolChain.h @@ -134,7 +134,7 @@ public: StringRef getOS() const { return Triple.getOSName(); } /// \brief Provide the default architecture name (as expected by -arch) for - /// this toolchain. Note t + /// this toolchain. StringRef getDefaultUniversalArchName() const; std::string getTripleString() const { diff --git a/include/clang/Lex/LiteralSupport.h b/include/clang/Lex/LiteralSupport.h index 5210e3f2e1c5..d568614e2ae4 100644 --- a/include/clang/Lex/LiteralSupport.h +++ b/include/clang/Lex/LiteralSupport.h @@ -166,6 +166,7 @@ public: bool hadError() const { return HadError; } bool isAscii() const { return Kind == tok::char_constant; } bool isWide() const { return Kind == tok::wide_char_constant; } + bool isUTF8() const { return Kind == tok::utf8_char_constant; } bool isUTF16() const { return Kind == tok::utf16_char_constant; } bool isUTF32() const { return Kind == tok::utf32_char_constant; } bool isMultiChar() const { return IsMultiChar; } diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 82b779879c20..00885a5c7103 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -501,6 +501,10 @@ private: /// #pragma align... void HandlePragmaAlign(); + /// \brief Handle the annotation token produced for + /// #pragma clang __debug dump... + void HandlePragmaDump(); + /// \brief Handle the annotation token produced for /// #pragma weak id... void HandlePragmaWeak(); @@ -1640,13 +1644,22 @@ private: /// A SmallVector of types. typedef SmallVector TypeVector; - StmtResult ParseStatement(SourceLocation *TrailingElseLoc = nullptr); + StmtResult ParseStatement(SourceLocation *TrailingElseLoc = nullptr, + bool AllowOpenMPStandalone = false); + enum AllowedContsructsKind { + /// \brief Allow any declarations, statements, OpenMP directives. + ACK_Any, + /// \brief Allow only statements and non-standalone OpenMP directives. + ACK_StatementsOpenMPNonStandalone, + /// \brief Allow statements and all executable OpenMP directives + ACK_StatementsOpenMPAnyExecutable + }; StmtResult - ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement, + ParseStatementOrDeclaration(StmtVector &Stmts, AllowedContsructsKind Allowed, SourceLocation *TrailingElseLoc = nullptr); StmtResult ParseStatementOrDeclarationAfterAttributes( StmtVector &Stmts, - bool OnlyStatement, + AllowedContsructsKind Allowed, SourceLocation *TrailingElseLoc, ParsedAttributesWithRange &Attrs); StmtResult ParseExprStatement(); @@ -1674,7 +1687,8 @@ private: StmtResult ParseReturnStatement(); StmtResult ParseAsmStatement(bool &msAsm); StmtResult ParseMicrosoftAsmStatement(SourceLocation AsmLoc); - StmtResult ParsePragmaLoopHint(StmtVector &Stmts, bool OnlyStatement, + StmtResult ParsePragmaLoopHint(StmtVector &Stmts, + AllowedContsructsKind Allowed, SourceLocation *TrailingElseLoc, ParsedAttributesWithRange &Attrs); @@ -2439,11 +2453,13 @@ private: bool AllowScopeSpecifier); /// \brief Parses declarative or executable directive. /// - /// \param StandAloneAllowed true if allowed stand-alone directives, - /// false - otherwise + /// \param Allowed ACK_Any, if any directives are allowed, + /// ACK_StatementsOpenMPAnyExecutable - if any executable directives are + /// allowed, ACK_StatementsOpenMPNonStandalone - if only non-standalone + /// executable directives are allowed. /// StmtResult - ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed); + ParseOpenMPDeclarativeOrExecutableDirective(AllowedContsructsKind Allowed); /// \brief Parses clause of kind \a CKind for directive of a kind \a Kind. /// /// \param DKind Kind of current directive. diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h index e9fdb707f277..064d37b2a02b 100644 --- a/include/clang/Sema/DeclSpec.h +++ b/include/clang/Sema/DeclSpec.h @@ -337,6 +337,7 @@ private: unsigned TypeAltiVecPixel : 1; unsigned TypeAltiVecBool : 1; unsigned TypeSpecOwned : 1; + unsigned TypeSpecPipe : 1; // type-qualifiers unsigned TypeQualifiers : 4; // Bitwise OR of TQ. @@ -385,6 +386,7 @@ private: SourceLocation FS_inlineLoc, FS_virtualLoc, FS_explicitLoc, FS_noreturnLoc; SourceLocation FS_forceinlineLoc; SourceLocation FriendLoc, ModulePrivateLoc, ConstexprLoc, ConceptLoc; + SourceLocation TQ_pipeLoc; WrittenBuiltinSpecs writtenBS; void SaveWrittenBuiltinSpecs(); @@ -420,6 +422,7 @@ public: TypeAltiVecPixel(false), TypeAltiVecBool(false), TypeSpecOwned(false), + TypeSpecPipe(false), TypeQualifiers(TQ_unspecified), FS_inline_specified(false), FS_forceinline_specified(false), @@ -473,6 +476,7 @@ public: bool isTypeAltiVecBool() const { return TypeAltiVecBool; } bool isTypeSpecOwned() const { return TypeSpecOwned; } bool isTypeRep() const { return isTypeRep((TST) TypeSpecType); } + bool isTypeSpecPipe() const { return TypeSpecPipe; } ParsedType getRepAsType() const { assert(isTypeRep((TST) TypeSpecType) && "DeclSpec does not store a type"); @@ -532,6 +536,7 @@ public: SourceLocation getRestrictSpecLoc() const { return TQ_restrictLoc; } SourceLocation getVolatileSpecLoc() const { return TQ_volatileLoc; } SourceLocation getAtomicSpecLoc() const { return TQ_atomicLoc; } + SourceLocation getPipeLoc() const { return TQ_pipeLoc; } /// \brief Clear out all of the type qualifiers. void ClearTypeQualifiers() { @@ -540,6 +545,7 @@ public: TQ_restrictLoc = SourceLocation(); TQ_volatileLoc = SourceLocation(); TQ_atomicLoc = SourceLocation(); + TQ_pipeLoc = SourceLocation(); } // function-specifier @@ -643,6 +649,9 @@ public: bool SetTypeAltiVecBool(bool isAltiVecBool, SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID, const PrintingPolicy &Policy); + bool SetTypePipe(bool isPipe, SourceLocation Loc, + const char *&PrevSpec, unsigned &DiagID, + const PrintingPolicy &Policy); bool SetTypeSpecError(); void UpdateDeclRep(Decl *Rep) { assert(isDeclRep((TST) TypeSpecType)); @@ -1081,7 +1090,7 @@ typedef SmallVector CachedTokens; /// This is intended to be a small value object. struct DeclaratorChunk { enum { - Pointer, Reference, Array, Function, BlockPointer, MemberPointer, Paren + Pointer, Reference, Array, Function, BlockPointer, MemberPointer, Paren, Pipe } Kind; /// Loc - The place where this type was defined. @@ -1409,6 +1418,13 @@ struct DeclaratorChunk { } }; + struct PipeTypeInfo : TypeInfoCommon { + /// The access writes. + unsigned AccessWrites : 3; + + void destroy() {} + }; + union { TypeInfoCommon Common; PointerTypeInfo Ptr; @@ -1417,6 +1433,7 @@ struct DeclaratorChunk { FunctionTypeInfo Fun; BlockPointerTypeInfo Cls; MemberPointerTypeInfo Mem; + PipeTypeInfo PipeInfo; }; void destroy() { @@ -1428,6 +1445,7 @@ struct DeclaratorChunk { case DeclaratorChunk::Array: return Arr.destroy(); case DeclaratorChunk::MemberPointer: return Mem.destroy(); case DeclaratorChunk::Paren: return; + case DeclaratorChunk::Pipe: return PipeInfo.destroy(); } } @@ -1526,6 +1544,17 @@ struct DeclaratorChunk { return I; } + /// \brief Return a DeclaratorChunk for a block. + static DeclaratorChunk getPipe(unsigned TypeQuals, + SourceLocation Loc) { + DeclaratorChunk I; + I.Kind = Pipe; + I.Loc = Loc; + I.Cls.TypeQuals = TypeQuals; + I.Cls.AttrList = 0; + return I; + } + static DeclaratorChunk getMemberPointer(const CXXScopeSpec &SS, unsigned TypeQuals, SourceLocation Loc) { @@ -2026,6 +2055,7 @@ public: case DeclaratorChunk::Array: case DeclaratorChunk::BlockPointer: case DeclaratorChunk::MemberPointer: + case DeclaratorChunk::Pipe: return false; } llvm_unreachable("Invalid type chunk"); diff --git a/include/clang/Sema/Lookup.h b/include/clang/Sema/Lookup.h index 87c40f0cf206..7efb19f57419 100644 --- a/include/clang/Sema/Lookup.h +++ b/include/clang/Sema/Lookup.h @@ -515,6 +515,7 @@ public: configure(); } + void dump(); void print(raw_ostream &); /// Suppress the diagnostics that would normally fire because of this diff --git a/include/clang/Sema/Overload.h b/include/clang/Sema/Overload.h index 20958b057a4f..62437953b35b 100644 --- a/include/clang/Sema/Overload.h +++ b/include/clang/Sema/Overload.h @@ -570,8 +570,8 @@ namespace clang { /// This conversion candidate is not viable because its result /// type is not implicitly convertible to the desired type. ovl_fail_bad_final_conversion, - - /// This conversion function template specialization candidate is not + + /// This conversion function template specialization candidate is not /// viable because the final conversion was not an exact match. ovl_fail_final_conversion_not_exact, @@ -582,7 +582,10 @@ namespace clang { /// This candidate function was not viable because an enable_if /// attribute disabled it. - ovl_fail_enable_if + ovl_fail_enable_if, + + /// This candidate was not viable because its address could not be taken. + ovl_fail_addr_not_available }; /// OverloadCandidate - A single candidate in an overload set (C++ 13.3). diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 77d06f2affb7..ffe1ff3b950b 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -1269,6 +1269,8 @@ public: SourceLocation Loc, DeclarationName Entity); QualType BuildParenType(QualType T); QualType BuildAtomicType(QualType T, SourceLocation Loc); + QualType BuildPipeType(QualType T, + SourceLocation Loc); TypeSourceInfo *GetTypeForDeclarator(Declarator &D, Scope *S); TypeSourceInfo *GetTypeForDeclaratorCast(Declarator &D, QualType FromTy); @@ -2548,7 +2550,8 @@ public: MultiExprArg Args, SourceLocation RParenLoc, Expr *ExecConfig, - bool AllowTypoCorrection=true); + bool AllowTypoCorrection=true, + bool CalleesAddressIsTaken=false); bool buildOverloadedCallSet(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, MultiExprArg Args, SourceLocation RParenLoc, @@ -7626,6 +7629,9 @@ public: void ActOnPragmaMSInitSeg(SourceLocation PragmaLocation, StringLiteral *SegmentName); + /// \brief Called on #pragma clang __debug dump II + void ActOnPragmaDump(Scope *S, SourceLocation Loc, IdentifierInfo *II); + /// ActOnPragmaDetectMismatch - Call on well-formed \#pragma detect_mismatch void ActOnPragmaDetectMismatch(StringRef Name, StringRef Value); @@ -8583,6 +8589,10 @@ public: bool CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty, CastKind &Kind); + /// \brief Prepare `SplattedExpr` for a vector splat operation, adding + /// implicit casts if necessary. + ExprResult prepareVectorSplat(QualType VectorTy, Expr *SplattedExpr); + // CheckExtVectorCast - check type constraints for extended vectors. // Since vectors are an extension, there are no C standard reference for this. // We allow casting between vectors and integer datatypes of the same size, diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h index 16bda6ea03c1..0dfb8cf37146 100644 --- a/include/clang/Serialization/ASTBitCodes.h +++ b/include/clang/Serialization/ASTBitCodes.h @@ -907,7 +907,9 @@ namespace clang { /// \brief A DecayedType record. TYPE_DECAYED = 41, /// \brief An AdjustedType record. - TYPE_ADJUSTED = 42 + TYPE_ADJUSTED = 42, + /// \brief A PipeType record. + TYPE_PIPE = 43 }; /// \brief The type IDs for special types constructed by semantic diff --git a/include/clang/Serialization/ASTWriter.h b/include/clang/Serialization/ASTWriter.h index ed345472fc7d..ef8c65341388 100644 --- a/include/clang/Serialization/ASTWriter.h +++ b/include/clang/Serialization/ASTWriter.h @@ -871,6 +871,7 @@ public: const FunctionDecl *Delete) override; void CompletedImplicitDefinition(const FunctionDecl *D) override; void StaticDataMemberInstantiated(const VarDecl *D) override; + void DefaultArgumentInstantiated(const ParmVarDecl *D) override; void FunctionDefinitionInstantiated(const FunctionDecl *D) override; void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD, const ObjCInterfaceDecl *IFD) override; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h index bb835c4c565e..43f6e5cda0dc 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h @@ -80,7 +80,7 @@ class MemRegion : public llvm::FoldingSetNode { public: enum Kind { // Memory spaces. - GenericMemSpaceRegionKind, + CodeSpaceRegionKind, StackLocalsSpaceRegionKind, StackArgumentsSpaceRegionKind, HeapSpaceRegionKind, @@ -89,29 +89,29 @@ public: GlobalInternalSpaceRegionKind, GlobalSystemSpaceRegionKind, GlobalImmutableSpaceRegionKind, - BEG_NON_STATIC_GLOBAL_MEMSPACES = GlobalInternalSpaceRegionKind, + BEGIN_NON_STATIC_GLOBAL_MEMSPACES = GlobalInternalSpaceRegionKind, END_NON_STATIC_GLOBAL_MEMSPACES = GlobalImmutableSpaceRegionKind, - BEG_GLOBAL_MEMSPACES = StaticGlobalSpaceRegionKind, + BEGIN_GLOBAL_MEMSPACES = StaticGlobalSpaceRegionKind, END_GLOBAL_MEMSPACES = GlobalImmutableSpaceRegionKind, - BEG_MEMSPACES = GenericMemSpaceRegionKind, + BEGIN_MEMSPACES = CodeSpaceRegionKind, END_MEMSPACES = GlobalImmutableSpaceRegionKind, // Untyped regions. SymbolicRegionKind, AllocaRegionKind, // Typed regions. - BEG_TYPED_REGIONS, - FunctionTextRegionKind = BEG_TYPED_REGIONS, - BlockTextRegionKind, + BEGIN_TYPED_REGIONS, + FunctionCodeRegionKind = BEGIN_TYPED_REGIONS, + BlockCodeRegionKind, BlockDataRegionKind, - BEG_TYPED_VALUE_REGIONS, - CompoundLiteralRegionKind = BEG_TYPED_VALUE_REGIONS, + BEGIN_TYPED_VALUE_REGIONS, + CompoundLiteralRegionKind = BEGIN_TYPED_VALUE_REGIONS, CXXThisRegionKind, StringRegionKind, ObjCStringRegionKind, ElementRegionKind, // Decl Regions. - BEG_DECL_REGIONS, - VarRegionKind = BEG_DECL_REGIONS, + BEGIN_DECL_REGIONS, + VarRegionKind = BEGIN_DECL_REGIONS, FieldRegionKind, ObjCIvarRegionKind, END_DECL_REGIONS = ObjCIvarRegionKind, @@ -193,12 +193,9 @@ public: /// for example, the set of global variables, the stack frame, etc. class MemSpaceRegion : public MemRegion { protected: - friend class MemRegionManager; - MemRegionManager *Mgr; - MemSpaceRegion(MemRegionManager *mgr, Kind k = GenericMemSpaceRegionKind) - : MemRegion(k), Mgr(mgr) { + MemSpaceRegion(MemRegionManager *mgr, Kind k) : MemRegion(k), Mgr(mgr) { assert(classof(this)); } @@ -211,10 +208,26 @@ public: static bool classof(const MemRegion *R) { Kind k = R->getKind(); - return k >= BEG_MEMSPACES && k <= END_MEMSPACES; + return k >= BEGIN_MEMSPACES && k <= END_MEMSPACES; } }; - + +/// CodeSpaceRegion - The memory space that holds the executable code of +/// functions and blocks. +class CodeSpaceRegion : public MemSpaceRegion { + friend class MemRegionManager; + + CodeSpaceRegion(MemRegionManager *mgr) + : MemSpaceRegion(mgr, CodeSpaceRegionKind) {} + +public: + void dumpToStream(raw_ostream &os) const override; + + static bool classof(const MemRegion *R) { + return R->getKind() == CodeSpaceRegionKind; + } +}; + class GlobalsSpaceRegion : public MemSpaceRegion { virtual void anchor(); protected: @@ -223,7 +236,7 @@ protected: public: static bool classof(const MemRegion *R) { Kind k = R->getKind(); - return k >= BEG_GLOBAL_MEMSPACES && k <= END_GLOBAL_MEMSPACES; + return k >= BEGIN_GLOBAL_MEMSPACES && k <= END_GLOBAL_MEMSPACES; } }; @@ -259,17 +272,15 @@ public: /// RegionStoreManager::invalidateRegions (instead of finding all the dependent /// globals, we invalidate the whole parent region). class NonStaticGlobalSpaceRegion : public GlobalsSpaceRegion { - friend class MemRegionManager; - protected: NonStaticGlobalSpaceRegion(MemRegionManager *mgr, Kind k) : GlobalsSpaceRegion(mgr, k) {} - + public: static bool classof(const MemRegion *R) { Kind k = R->getKind(); - return k >= BEG_NON_STATIC_GLOBAL_MEMSPACES && + return k >= BEGIN_NON_STATIC_GLOBAL_MEMSPACES && k <= END_NON_STATIC_GLOBAL_MEMSPACES; } }; @@ -357,7 +368,7 @@ public: return R->getKind() == UnknownSpaceRegionKind; } }; - + class StackSpaceRegion : public MemSpaceRegion { private: const StackFrameContext *SFC; @@ -368,18 +379,18 @@ protected: assert(classof(this)); } -public: +public: const StackFrameContext *getStackFrame() const { return SFC; } - + void Profile(llvm::FoldingSetNodeID &ID) const override; static bool classof(const MemRegion *R) { Kind k = R->getKind(); return k >= StackLocalsSpaceRegionKind && k <= StackArgumentsSpaceRegionKind; - } + } }; - + class StackLocalsSpaceRegion : public StackSpaceRegion { virtual void anchor(); friend class MemRegionManager; @@ -491,7 +502,7 @@ public: static bool classof(const MemRegion* R) { unsigned k = R->getKind(); - return k >= BEG_TYPED_REGIONS && k <= END_TYPED_REGIONS; + return k >= BEGIN_TYPED_REGIONS && k <= END_TYPED_REGIONS; } }; @@ -523,7 +534,7 @@ public: static bool classof(const MemRegion* R) { unsigned k = R->getKind(); - return k >= BEG_TYPED_VALUE_REGIONS && k <= END_TYPED_VALUE_REGIONS; + return k >= BEGIN_TYPED_VALUE_REGIONS && k <= END_TYPED_VALUE_REGIONS; } }; @@ -538,16 +549,16 @@ public: static bool classof(const MemRegion* R) { Kind k = R->getKind(); - return k >= FunctionTextRegionKind && k <= BlockTextRegionKind; + return k >= FunctionCodeRegionKind && k <= BlockCodeRegionKind; } }; -/// FunctionTextRegion - A region that represents code texts of function. -class FunctionTextRegion : public CodeTextRegion { +/// FunctionCodeRegion - A region that represents code texts of function. +class FunctionCodeRegion : public CodeTextRegion { const NamedDecl *FD; public: - FunctionTextRegion(const NamedDecl *fd, const MemRegion* sreg) - : CodeTextRegion(sreg, FunctionTextRegionKind), FD(fd) { + FunctionCodeRegion(const NamedDecl *fd, const MemRegion* sreg) + : CodeTextRegion(sreg, FunctionCodeRegionKind), FD(fd) { assert(isa(fd) || isa(fd)); } @@ -577,27 +588,27 @@ public: const MemRegion*); static bool classof(const MemRegion* R) { - return R->getKind() == FunctionTextRegionKind; + return R->getKind() == FunctionCodeRegionKind; } }; -/// BlockTextRegion - A region that represents code texts of blocks (closures). -/// Blocks are represented with two kinds of regions. BlockTextRegions +/// BlockCodeRegion - A region that represents code texts of blocks (closures). +/// Blocks are represented with two kinds of regions. BlockCodeRegions /// represent the "code", while BlockDataRegions represent instances of blocks, /// which correspond to "code+data". The distinction is important, because /// like a closure a block captures the values of externally referenced /// variables. -class BlockTextRegion : public CodeTextRegion { +class BlockCodeRegion : public CodeTextRegion { friend class MemRegionManager; const BlockDecl *BD; AnalysisDeclContext *AC; CanQualType locTy; - BlockTextRegion(const BlockDecl *bd, CanQualType lTy, + BlockCodeRegion(const BlockDecl *bd, CanQualType lTy, AnalysisDeclContext *ac, const MemRegion* sreg) - : CodeTextRegion(sreg, BlockTextRegionKind), BD(bd), AC(ac), locTy(lTy) {} + : CodeTextRegion(sreg, BlockCodeRegionKind), BD(bd), AC(ac), locTy(lTy) {} public: QualType getLocationType() const override { @@ -619,32 +630,32 @@ public: const MemRegion*); static bool classof(const MemRegion* R) { - return R->getKind() == BlockTextRegionKind; + return R->getKind() == BlockCodeRegionKind; } }; /// BlockDataRegion - A region that represents a block instance. -/// Blocks are represented with two kinds of regions. BlockTextRegions +/// Blocks are represented with two kinds of regions. BlockCodeRegions /// represent the "code", while BlockDataRegions represent instances of blocks, /// which correspond to "code+data". The distinction is important, because /// like a closure a block captures the values of externally referenced /// variables. class BlockDataRegion : public TypedRegion { friend class MemRegionManager; - const BlockTextRegion *BC; + const BlockCodeRegion *BC; const LocationContext *LC; // Can be null */ unsigned BlockCount; void *ReferencedVars; void *OriginalVars; - BlockDataRegion(const BlockTextRegion *bc, const LocationContext *lc, + BlockDataRegion(const BlockCodeRegion *bc, const LocationContext *lc, unsigned count, const MemRegion *sreg) : TypedRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc), BlockCount(count), ReferencedVars(nullptr), OriginalVars(nullptr) {} public: - const BlockTextRegion *getCodeRegion() const { return BC; } + const BlockCodeRegion *getCodeRegion() const { return BC; } const BlockDecl *getDecl() const { return BC->getDecl(); } @@ -691,7 +702,7 @@ public: void Profile(llvm::FoldingSetNodeID& ID) const override; - static void ProfileRegion(llvm::FoldingSetNodeID&, const BlockTextRegion *, + static void ProfileRegion(llvm::FoldingSetNodeID&, const BlockCodeRegion *, const LocationContext *, unsigned, const MemRegion *); @@ -856,7 +867,7 @@ public: static bool classof(const MemRegion* R) { unsigned k = R->getKind(); - return k >= BEG_DECL_REGIONS && k <= END_DECL_REGIONS; + return k >= BEGIN_DECL_REGIONS && k <= END_DECL_REGIONS; } }; @@ -1138,7 +1149,7 @@ class MemRegionManager { HeapSpaceRegion *heap; UnknownSpaceRegion *unknown; - MemSpaceRegion *code; + CodeSpaceRegion *code; public: MemRegionManager(ASTContext &c, llvm::BumpPtrAllocator &a) @@ -1174,9 +1185,9 @@ public: /// getUnknownRegion - Retrieve the memory region associated with unknown /// memory space. - const MemSpaceRegion *getUnknownRegion(); + const UnknownSpaceRegion *getUnknownRegion(); - const MemSpaceRegion *getCodeRegion(); + const CodeSpaceRegion *getCodeRegion(); /// getAllocaRegion - Retrieve a region associated with a call to alloca(). const AllocaRegion *getAllocaRegion(const Expr *Ex, unsigned Cnt, @@ -1262,8 +1273,8 @@ public: baseReg->isVirtual()); } - const FunctionTextRegion *getFunctionTextRegion(const NamedDecl *FD); - const BlockTextRegion *getBlockTextRegion(const BlockDecl *BD, + const FunctionCodeRegion *getFunctionCodeRegion(const NamedDecl *FD); + const BlockCodeRegion *getBlockCodeRegion(const BlockDecl *BD, CanQualType locTy, AnalysisDeclContext *AC); @@ -1271,7 +1282,7 @@ public: /// of a block. Unlike many other MemRegions, the LocationContext* /// argument is allowed to be NULL for cases where we have no known /// context. - const BlockDataRegion *getBlockDataRegion(const BlockTextRegion *bc, + const BlockDataRegion *getBlockDataRegion(const BlockCodeRegion *bc, const LocationContext *lc, unsigned blockCount); diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h index a68d3410a87b..3c47114e2de2 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h @@ -83,7 +83,11 @@ public: } SVal evalCast(SVal val, QualType castTy, QualType originalType); - + + // Handles casts of type CK_IntegralCast. + SVal evalIntegralCast(ProgramStateRef state, SVal val, QualType castTy, + QualType originalType); + virtual SVal evalMinus(NonLoc val) = 0; virtual SVal evalComplement(NonLoc val) = 0; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h index 642e11af0e6c..d64425412c89 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h @@ -45,8 +45,8 @@ class SVal { public: enum BaseKind { // The enumerators must be representable using 2 bits. - UndefinedKind = 0, // for subclass UndefinedVal (an uninitialized value) - UnknownKind = 1, // for subclass UnknownVal (a void value) + UndefinedValKind = 0, // for subclass UndefinedVal (an uninitialized value) + UnknownValKind = 1, // for subclass UnknownVal (a void value) LocKind = 2, // for subclass Loc (an L-value) NonLocKind = 3 // for subclass NonLoc (an R-value that's not // an L-value) @@ -115,19 +115,19 @@ public: } inline bool isUnknown() const { - return getRawKind() == UnknownKind; + return getRawKind() == UnknownValKind; } inline bool isUndef() const { - return getRawKind() == UndefinedKind; + return getRawKind() == UndefinedValKind; } inline bool isUnknownOrUndef() const { - return getRawKind() <= UnknownKind; + return getRawKind() <= UnknownValKind; } inline bool isValid() const { - return getRawKind() > UnknownKind; + return getRawKind() > UnknownValKind; } bool isConstant() const; @@ -190,12 +190,12 @@ public: class UndefinedVal : public SVal { public: - UndefinedVal() : SVal(UndefinedKind) {} + UndefinedVal() : SVal(UndefinedValKind) {} private: friend class SVal; static bool isKind(const SVal& V) { - return V.getBaseKind() == UndefinedKind; + return V.getBaseKind() == UndefinedValKind; } }; @@ -223,12 +223,12 @@ private: class UnknownVal : public DefinedOrUnknownSVal { public: - explicit UnknownVal() : DefinedOrUnknownSVal(UnknownKind) {} + explicit UnknownVal() : DefinedOrUnknownSVal(UnknownValKind) {} private: friend class SVal; static bool isKind(const SVal &V) { - return V.getBaseKind() == UnknownKind; + return V.getBaseKind() == UnknownValKind; } }; @@ -465,7 +465,7 @@ private: namespace loc { -enum Kind { GotoLabelKind, MemRegionKind, ConcreteIntKind }; +enum Kind { GotoLabelKind, MemRegionValKind, ConcreteIntKind }; class GotoLabel : public Loc { public: @@ -490,7 +490,7 @@ private: class MemRegionVal : public Loc { public: - explicit MemRegionVal(const MemRegion* r) : Loc(MemRegionKind, r) {} + explicit MemRegionVal(const MemRegion* r) : Loc(MemRegionValKind, r) {} /// \brief Get the underlining region. const MemRegion* getRegion() const { @@ -518,11 +518,11 @@ private: MemRegionVal() {} static bool isKind(const SVal& V) { return V.getBaseKind() == LocKind && - V.getSubKind() == MemRegionKind; + V.getSubKind() == MemRegionValKind; } static bool isKind(const Loc& V) { - return V.getSubKind() == MemRegionKind; + return V.getSubKind() == MemRegionValKind; } }; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h index 9dbfab24b417..77d12e5ba666 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h @@ -42,14 +42,22 @@ namespace ento { class SymExpr : public llvm::FoldingSetNode { virtual void anchor(); public: - enum Kind { RegionValueKind, ConjuredKind, DerivedKind, ExtentKind, - MetadataKind, - BEGIN_SYMBOLS = RegionValueKind, - END_SYMBOLS = MetadataKind, - SymIntKind, IntSymKind, SymSymKind, - BEGIN_BINARYSYMEXPRS = SymIntKind, - END_BINARYSYMEXPRS = SymSymKind, - CastSymbolKind }; + enum Kind { + SymbolRegionValueKind, + SymbolConjuredKind, + SymbolDerivedKind, + SymbolExtentKind, + SymbolMetadataKind, + BEGIN_SYMBOLS = SymbolRegionValueKind, + END_SYMBOLS = SymbolMetadataKind, + SymIntExprKind, + IntSymExprKind, + SymSymExprKind, + BEGIN_BINARYSYMEXPRS = SymIntExprKind, + END_BINARYSYMEXPRS = SymSymExprKind, + SymbolCastKind + }; + private: Kind K; @@ -126,12 +134,12 @@ class SymbolRegionValue : public SymbolData { public: SymbolRegionValue(SymbolID sym, const TypedValueRegion *r) - : SymbolData(RegionValueKind, sym), R(r) {} + : SymbolData(SymbolRegionValueKind, sym), R(r) {} const TypedValueRegion* getRegion() const { return R; } static void Profile(llvm::FoldingSetNodeID& profile, const TypedValueRegion* R) { - profile.AddInteger((unsigned) RegionValueKind); + profile.AddInteger((unsigned) SymbolRegionValueKind); profile.AddPointer(R); } @@ -145,7 +153,7 @@ public: // Implement isa support. static inline bool classof(const SymExpr *SE) { - return SE->getKind() == RegionValueKind; + return SE->getKind() == SymbolRegionValueKind; } }; @@ -160,11 +168,9 @@ class SymbolConjured : public SymbolData { public: SymbolConjured(SymbolID sym, const Stmt *s, const LocationContext *lctx, - QualType t, unsigned count, - const void *symbolTag) - : SymbolData(ConjuredKind, sym), S(s), T(t), Count(count), - LCtx(lctx), - SymbolTag(symbolTag) {} + QualType t, unsigned count, const void *symbolTag) + : SymbolData(SymbolConjuredKind, sym), S(s), T(t), Count(count), + LCtx(lctx), SymbolTag(symbolTag) {} const Stmt *getStmt() const { return S; } unsigned getCount() const { return Count; } @@ -177,7 +183,7 @@ public: static void Profile(llvm::FoldingSetNodeID& profile, const Stmt *S, QualType T, unsigned Count, const LocationContext *LCtx, const void *SymbolTag) { - profile.AddInteger((unsigned) ConjuredKind); + profile.AddInteger((unsigned) SymbolConjuredKind); profile.AddPointer(S); profile.AddPointer(LCtx); profile.Add(T); @@ -191,7 +197,7 @@ public: // Implement isa support. static inline bool classof(const SymExpr *SE) { - return SE->getKind() == ConjuredKind; + return SE->getKind() == SymbolConjuredKind; } }; @@ -203,7 +209,7 @@ class SymbolDerived : public SymbolData { public: SymbolDerived(SymbolID sym, SymbolRef parent, const TypedValueRegion *r) - : SymbolData(DerivedKind, sym), parentSymbol(parent), R(r) {} + : SymbolData(SymbolDerivedKind, sym), parentSymbol(parent), R(r) {} SymbolRef getParentSymbol() const { return parentSymbol; } const TypedValueRegion *getRegion() const { return R; } @@ -214,7 +220,7 @@ public: static void Profile(llvm::FoldingSetNodeID& profile, SymbolRef parent, const TypedValueRegion *r) { - profile.AddInteger((unsigned) DerivedKind); + profile.AddInteger((unsigned) SymbolDerivedKind); profile.AddPointer(r); profile.AddPointer(parent); } @@ -225,7 +231,7 @@ public: // Implement isa support. static inline bool classof(const SymExpr *SE) { - return SE->getKind() == DerivedKind; + return SE->getKind() == SymbolDerivedKind; } }; @@ -237,7 +243,7 @@ class SymbolExtent : public SymbolData { public: SymbolExtent(SymbolID sym, const SubRegion *r) - : SymbolData(ExtentKind, sym), R(r) {} + : SymbolData(SymbolExtentKind, sym), R(r) {} const SubRegion *getRegion() const { return R; } @@ -246,7 +252,7 @@ public: void dumpToStream(raw_ostream &os) const override; static void Profile(llvm::FoldingSetNodeID& profile, const SubRegion *R) { - profile.AddInteger((unsigned) ExtentKind); + profile.AddInteger((unsigned) SymbolExtentKind); profile.AddPointer(R); } @@ -256,7 +262,7 @@ public: // Implement isa support. static inline bool classof(const SymExpr *SE) { - return SE->getKind() == ExtentKind; + return SE->getKind() == SymbolExtentKind; } }; @@ -273,7 +279,7 @@ class SymbolMetadata : public SymbolData { public: SymbolMetadata(SymbolID sym, const MemRegion* r, const Stmt *s, QualType t, unsigned count, const void *tag) - : SymbolData(MetadataKind, sym), R(r), S(s), T(t), Count(count), Tag(tag) {} + : SymbolData(SymbolMetadataKind, sym), R(r), S(s), T(t), Count(count), Tag(tag) {} const MemRegion *getRegion() const { return R; } const Stmt *getStmt() const { return S; } @@ -287,7 +293,7 @@ public: static void Profile(llvm::FoldingSetNodeID& profile, const MemRegion *R, const Stmt *S, QualType T, unsigned Count, const void *Tag) { - profile.AddInteger((unsigned) MetadataKind); + profile.AddInteger((unsigned) SymbolMetadataKind); profile.AddPointer(R); profile.AddPointer(S); profile.Add(T); @@ -301,7 +307,7 @@ public: // Implement isa support. static inline bool classof(const SymExpr *SE) { - return SE->getKind() == MetadataKind; + return SE->getKind() == SymbolMetadataKind; } }; @@ -315,7 +321,7 @@ class SymbolCast : public SymExpr { public: SymbolCast(const SymExpr *In, QualType From, QualType To) : - SymExpr(CastSymbolKind), Operand(In), FromTy(From), ToTy(To) { } + SymExpr(SymbolCastKind), Operand(In), FromTy(From), ToTy(To) { } QualType getType() const override { return ToTy; } @@ -325,7 +331,7 @@ public: static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *In, QualType From, QualType To) { - ID.AddInteger((unsigned) CastSymbolKind); + ID.AddInteger((unsigned) SymbolCastKind); ID.AddPointer(In); ID.Add(From); ID.Add(To); @@ -337,7 +343,7 @@ public: // Implement isa support. static inline bool classof(const SymExpr *SE) { - return SE->getKind() == CastSymbolKind; + return SE->getKind() == SymbolCastKind; } }; @@ -372,7 +378,7 @@ class SymIntExpr : public BinarySymExpr { public: SymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op, const llvm::APSInt& rhs, QualType t) - : BinarySymExpr(SymIntKind, op, t), LHS(lhs), RHS(rhs) {} + : BinarySymExpr(SymIntExprKind, op, t), LHS(lhs), RHS(rhs) {} void dumpToStream(raw_ostream &os) const override; @@ -382,7 +388,7 @@ public: static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *lhs, BinaryOperator::Opcode op, const llvm::APSInt& rhs, QualType t) { - ID.AddInteger((unsigned) SymIntKind); + ID.AddInteger((unsigned) SymIntExprKind); ID.AddPointer(lhs); ID.AddInteger(op); ID.AddPointer(&rhs); @@ -395,7 +401,7 @@ public: // Implement isa support. static inline bool classof(const SymExpr *SE) { - return SE->getKind() == SymIntKind; + return SE->getKind() == SymIntExprKind; } }; @@ -407,7 +413,7 @@ class IntSymExpr : public BinarySymExpr { public: IntSymExpr(const llvm::APSInt& lhs, BinaryOperator::Opcode op, const SymExpr *rhs, QualType t) - : BinarySymExpr(IntSymKind, op, t), LHS(lhs), RHS(rhs) {} + : BinarySymExpr(IntSymExprKind, op, t), LHS(lhs), RHS(rhs) {} void dumpToStream(raw_ostream &os) const override; @@ -417,7 +423,7 @@ public: static void Profile(llvm::FoldingSetNodeID& ID, const llvm::APSInt& lhs, BinaryOperator::Opcode op, const SymExpr *rhs, QualType t) { - ID.AddInteger((unsigned) IntSymKind); + ID.AddInteger((unsigned) IntSymExprKind); ID.AddPointer(&lhs); ID.AddInteger(op); ID.AddPointer(rhs); @@ -430,7 +436,7 @@ public: // Implement isa support. static inline bool classof(const SymExpr *SE) { - return SE->getKind() == IntSymKind; + return SE->getKind() == IntSymExprKind; } }; @@ -442,7 +448,7 @@ class SymSymExpr : public BinarySymExpr { public: SymSymExpr(const SymExpr *lhs, BinaryOperator::Opcode op, const SymExpr *rhs, QualType t) - : BinarySymExpr(SymSymKind, op, t), LHS(lhs), RHS(rhs) {} + : BinarySymExpr(SymSymExprKind, op, t), LHS(lhs), RHS(rhs) {} const SymExpr *getLHS() const { return LHS; } const SymExpr *getRHS() const { return RHS; } @@ -451,7 +457,7 @@ public: static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *lhs, BinaryOperator::Opcode op, const SymExpr *rhs, QualType t) { - ID.AddInteger((unsigned) SymSymKind); + ID.AddInteger((unsigned) SymSymExprKind); ID.AddPointer(lhs); ID.AddInteger(op); ID.AddPointer(rhs); @@ -464,7 +470,7 @@ public: // Implement isa support. static inline bool classof(const SymExpr *SE) { - return SE->getKind() == SymSymKind; + return SE->getKind() == SymSymExprKind; } }; diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index d4abbe47cafb..64386967b220 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -1836,6 +1836,13 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { Align = static_cast(Width); } } + break; + + case Type::Pipe: { + TypeInfo Info = getTypeInfo(cast(T)->getElementType()); + Width = Info.Width; + Align = Info.Align; + } } @@ -2663,6 +2670,7 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const { case Type::FunctionProto: case Type::BlockPointer: case Type::MemberPointer: + case Type::Pipe: return type; // These types can be variably-modified. All these modifications @@ -3117,6 +3125,32 @@ ASTContext::getFunctionType(QualType ResultTy, ArrayRef ArgArray, return QualType(FTP, 0); } +/// Return pipe type for the specified type. +QualType ASTContext::getPipeType(QualType T) const { + llvm::FoldingSetNodeID ID; + PipeType::Profile(ID, T); + + void *InsertPos = 0; + if (PipeType *PT = PipeTypes.FindNodeOrInsertPos(ID, InsertPos)) + return QualType(PT, 0); + + // If the pipe element type isn't canonical, this won't be a canonical type + // either, so fill in the canonical type field. + QualType Canonical; + if (!T.isCanonical()) { + Canonical = getPipeType(getCanonicalType(T)); + + // Get the new insert position for the node we care about. + PipeType *NewIP = PipeTypes.FindNodeOrInsertPos(ID, InsertPos); + assert(!NewIP && "Shouldn't be in the map!"); + (void)NewIP; + } + PipeType *New = new (*this, TypeAlignment) PipeType(T, Canonical); + Types.push_back(New); + PipeTypes.InsertNode(New, InsertPos); + return QualType(New, 0); +} + #ifndef NDEBUG static bool NeedsInjectedClassNameType(const RecordDecl *D) { if (!isa(D)) return false; @@ -5857,6 +5891,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, case Type::Auto: return; + case Type::Pipe: #define ABSTRACT_TYPE(KIND, BASE) #define TYPE(KIND, BASE) #define DEPENDENT_TYPE(KIND, BASE) \ @@ -7792,6 +7827,24 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, return QualType(); } + case Type::Pipe: + { + // Merge two pointer types, while trying to preserve typedef info + QualType LHSValue = LHS->getAs()->getElementType(); + QualType RHSValue = RHS->getAs()->getElementType(); + if (Unqualified) { + LHSValue = LHSValue.getUnqualifiedType(); + RHSValue = RHSValue.getUnqualifiedType(); + } + QualType ResultType = mergeTypes(LHSValue, RHSValue, false, + Unqualified); + if (ResultType.isNull()) return QualType(); + if (getCanonicalType(LHSValue) == getCanonicalType(ResultType)) + return LHS; + if (getCanonicalType(RHSValue) == getCanonicalType(ResultType)) + return RHS; + return getPipeType(ResultType); + } } llvm_unreachable("Invalid Type::Class!"); diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp index e7fee0316b69..4622a75ac2c6 100644 --- a/lib/AST/ASTDumper.cpp +++ b/lib/AST/ASTDumper.cpp @@ -1055,6 +1055,7 @@ void ASTDumper::VisitTypedefDecl(const TypedefDecl *D) { dumpType(D->getUnderlyingType()); if (D->isModulePrivate()) OS << " __module_private__"; + dumpTypeAsChild(D->getUnderlyingType()); } void ASTDumper::VisitEnumDecl(const EnumDecl *D) { @@ -1226,6 +1227,7 @@ void ASTDumper::VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) { void ASTDumper::VisitTypeAliasDecl(const TypeAliasDecl *D) { dumpName(D); dumpType(D->getUnderlyingType()); + dumpTypeAsChild(D->getUnderlyingType()); } void ASTDumper::VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D) { @@ -1419,6 +1421,8 @@ void ASTDumper::VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) void ASTDumper::VisitUsingShadowDecl(const UsingShadowDecl *D) { OS << ' '; dumpBareDeclRef(D->getTargetDecl()); + if (auto *TD = dyn_cast(D->getUnderlyingDecl())) + dumpTypeAsChild(TD->getTypeForDecl()); } void ASTDumper::VisitLinkageSpecDecl(const LinkageSpecDecl *D) { diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 359db1ba81b3..916f1081798d 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -878,6 +878,14 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, break; } + case Type::Pipe: { + if (!IsStructurallyEquivalent(Context, + cast(T1)->getElementType(), + cast(T2)->getElementType())) + return false; + break; + } + } // end switch return true; diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 42bebc543e3e..427ca5efcd69 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -1184,7 +1184,7 @@ static LinkageInfo getLVForLocalDecl(const NamedDecl *D, return LinkageInfo::none(); const Decl *OuterD = getOutermostFuncOrBlockContext(D); - if (!OuterD) + if (!OuterD || OuterD->isInvalidDecl()) return LinkageInfo::none(); LinkageInfo LV; @@ -4024,16 +4024,26 @@ EnumConstantDecl::CreateDeserialized(ASTContext &C, unsigned ID) { void IndirectFieldDecl::anchor() { } +IndirectFieldDecl::IndirectFieldDecl(ASTContext &C, DeclContext *DC, + SourceLocation L, DeclarationName N, + QualType T, NamedDecl **CH, unsigned CHS) + : ValueDecl(IndirectField, DC, L, N, T), Chaining(CH), ChainingSize(CHS) { + // In C++, indirect field declarations conflict with tag declarations in the + // same scope, so add them to IDNS_Tag so that tag redeclaration finds them. + if (C.getLangOpts().CPlusPlus) + IdentifierNamespace |= IDNS_Tag; +} + IndirectFieldDecl * IndirectFieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, QualType T, NamedDecl **CH, unsigned CHS) { - return new (C, DC) IndirectFieldDecl(DC, L, Id, T, CH, CHS); + return new (C, DC) IndirectFieldDecl(C, DC, L, Id, T, CH, CHS); } IndirectFieldDecl *IndirectFieldDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - return new (C, ID) IndirectFieldDecl(nullptr, SourceLocation(), + return new (C, ID) IndirectFieldDecl(C, nullptr, SourceLocation(), DeclarationName(), QualType(), nullptr, 0); } diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index 16394e865eb1..72587e388e47 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -569,7 +569,6 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case Var: case ImplicitParam: case ParmVar: - case NonTypeTemplateParm: case ObjCMethod: case ObjCProperty: case MSProperty: @@ -579,6 +578,12 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case IndirectField: return IDNS_Ordinary | IDNS_Member; + case NonTypeTemplateParm: + // Non-type template parameters are not found by lookups that ignore + // non-types, but they are found by redeclaration lookups for tag types, + // so we include them in the tag namespace. + return IDNS_Ordinary | IDNS_Tag; + case ObjCCompatibleAlias: case ObjCInterface: return IDNS_Ordinary | IDNS_Type; diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index f9757b209294..52f34df43565 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -1553,6 +1553,7 @@ bool CastExpr::CastConsistency() const { case CK_ToVoid: case CK_VectorSplat: case CK_IntegralCast: + case CK_BooleanToSignedIntegral: case CK_IntegralToFloating: case CK_FloatingToIntegral: case CK_FloatingCast: @@ -1646,6 +1647,8 @@ const char *CastExpr::getCastKindName() const { return "VectorSplat"; case CK_IntegralCast: return "IntegralCast"; + case CK_BooleanToSignedIntegral: + return "BooleanToSignedIntegral"; case CK_IntegralToBoolean: return "IntegralToBoolean"; case CK_IntegralToFloating: diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index d35efcb101b5..ea983340a293 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -763,14 +763,6 @@ const IdentifierInfo *UserDefinedLiteral::getUDSuffix() const { return cast(getCalleeDecl())->getLiteralIdentifier(); } -CXXDefaultArgExpr * -CXXDefaultArgExpr::Create(const ASTContext &C, SourceLocation Loc, - ParmVarDecl *Param, Expr *SubExpr) { - void *Mem = C.Allocate(totalSizeToAlloc(1)); - return new (Mem) CXXDefaultArgExpr(CXXDefaultArgExprClass, Loc, Param, - SubExpr); -} - CXXDefaultInitExpr::CXXDefaultInitExpr(const ASTContext &C, SourceLocation Loc, FieldDecl *Field, QualType T) : Expr(CXXDefaultInitExprClass, T.getNonLValueExprType(C), diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index c4c4398c3622..fa652ba1b0ab 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -7781,12 +7781,16 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_PointerToBoolean: case CK_IntegralToBoolean: case CK_FloatingToBoolean: + case CK_BooleanToSignedIntegral: case CK_FloatingComplexToBoolean: case CK_IntegralComplexToBoolean: { bool BoolResult; if (!EvaluateAsBooleanCondition(SubExpr, BoolResult, Info)) return false; - return Success(BoolResult, E); + uint64_t IntResult = BoolResult; + if (BoolResult && E->getCastKind() == CK_BooleanToSignedIntegral) + IntResult = (uint64_t)-1; + return Success(IntResult, E); } case CK_IntegralCast: { @@ -8223,6 +8227,7 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_ToVoid: case CK_VectorSplat: case CK_IntegralCast: + case CK_BooleanToSignedIntegral: case CK_IntegralToBoolean: case CK_IntegralToFloating: case CK_FloatingToIntegral: diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp index 8018188a6b24..3f6b682f238f 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -1509,6 +1509,7 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty, case Type::ObjCInterface: case Type::ObjCObjectPointer: case Type::Atomic: + case Type::Pipe: llvm_unreachable("type is illegal as a nested name specifier"); case Type::SubstTemplateTypeParmPack: @@ -2682,6 +2683,13 @@ void CXXNameMangler::mangleType(const AtomicType *T) { mangleType(T->getValueType()); } +void CXXNameMangler::mangleType(const PipeType *T) { + // Pipe type mangling rules are described in SPIR 2.0 specification + // A.1 Data types and A.3 Summary of changes + // ::= 8ocl_pipe + Out << "8ocl_pipe"; +} + void CXXNameMangler::mangleIntegerLiteral(QualType T, const llvm::APSInt &Value) { // ::= L E # integer literal diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp index d45232b6deb0..4a45f9e4051f 100644 --- a/lib/AST/MicrosoftMangle.cpp +++ b/lib/AST/MicrosoftMangle.cpp @@ -2428,6 +2428,15 @@ void MicrosoftCXXNameMangler::mangleType(const AtomicType *T, Qualifiers, mangleArtificalTagType(TTK_Struct, TemplateMangling, {"__clang"}); } +void MicrosoftCXXNameMangler::mangleType(const PipeType *T, Qualifiers, + SourceRange Range) { + DiagnosticsEngine &Diags = Context.getDiags(); + unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, + "cannot mangle this OpenCL pipe type yet"); + Diags.Report(Range.getBegin(), DiagID) + << Range; +} + void MicrosoftMangleContextImpl::mangleCXXName(const NamedDecl *D, raw_ostream &Out) { assert((isa(D) || isa(D)) && diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index bc3c2a831c47..bc5ae0ffc469 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/lib/AST/RecordLayoutBuilder.cpp @@ -1552,7 +1552,8 @@ void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { FieldAlign = 1; // But, if there's an 'aligned' attribute on the field, honor that. - if (unsigned ExplicitFieldAlign = D->getMaxAlignment()) { + unsigned ExplicitFieldAlign = D->getMaxAlignment(); + if (ExplicitFieldAlign) { FieldAlign = std::max(FieldAlign, ExplicitFieldAlign); UnpackedFieldAlign = std::max(UnpackedFieldAlign, ExplicitFieldAlign); } @@ -1601,6 +1602,10 @@ void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { (AllowPadding && (FieldOffset & (FieldAlign-1)) + FieldSize > TypeSize)) { FieldOffset = llvm::RoundUpToAlignment(FieldOffset, FieldAlign); + } else if (ExplicitFieldAlign) { + // TODO: figure it out what needs to be done on targets that don't honor + // bit-field type alignment like ARM APCS ABI. + FieldOffset = llvm::RoundUpToAlignment(FieldOffset, ExplicitFieldAlign); } // Repeat the computation for diagnostic purposes. @@ -1609,6 +1614,9 @@ void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { (UnpackedFieldOffset & (UnpackedFieldAlign-1)) + FieldSize > TypeSize)) UnpackedFieldOffset = llvm::RoundUpToAlignment(UnpackedFieldOffset, UnpackedFieldAlign); + else if (ExplicitFieldAlign) + UnpackedFieldOffset = llvm::RoundUpToAlignment(UnpackedFieldOffset, + ExplicitFieldAlign); } // If we're using external layout, give the external layout a chance diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index e55b2fc19a1a..69f52f52b669 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -1165,6 +1165,7 @@ void StmtPrinter::VisitCharacterLiteral(CharacterLiteral *Node) { switch (Node->getKind()) { case CharacterLiteral::Ascii: break; // no prefix. case CharacterLiteral::Wide: OS << 'L'; break; + case CharacterLiteral::UTF8: OS << "u8"; break; case CharacterLiteral::UTF16: OS << 'u'; break; case CharacterLiteral::UTF32: OS << 'U'; break; } diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 7dd38cba229b..b467dac66b57 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -2614,7 +2614,7 @@ StringRef BuiltinType::getName(const PrintingPolicy &Policy) const { case OCLQueue: return "queue_t"; case OCLNDRange: - return "event_t"; + return "ndrange_t"; case OCLReserveID: return "reserve_id_t"; case OMPArraySection: @@ -3361,6 +3361,8 @@ static CachedProperties computeCachedProperties(const Type *T) { return Cache::get(cast(T)->getPointeeType()); case Type::Atomic: return Cache::get(cast(T)->getValueType()); + case Type::Pipe: + return Cache::get(cast(T)->getElementType()); } llvm_unreachable("unhandled type class"); @@ -3443,6 +3445,8 @@ static LinkageInfo computeLinkageInfo(const Type *T) { return computeLinkageInfo(cast(T)->getPointeeType()); case Type::Atomic: return computeLinkageInfo(cast(T)->getValueType()); + case Type::Pipe: + return computeLinkageInfo(cast(T)->getElementType()); } llvm_unreachable("unhandled type class"); @@ -3601,6 +3605,7 @@ bool Type::canHaveNullability() const { case Type::ObjCObject: case Type::ObjCInterface: case Type::Atomic: + case Type::Pipe: return false; } llvm_unreachable("bad type kind!"); diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp index 4617e1d3803f..b202523bdaf3 100644 --- a/lib/AST/TypePrinter.cpp +++ b/lib/AST/TypePrinter.cpp @@ -193,6 +193,7 @@ bool TypePrinter::canPrefixQualifiers(const Type *T, case Type::ObjCObject: case Type::ObjCInterface: case Type::Atomic: + case Type::Pipe: CanPrefixQualifiers = true; break; @@ -859,6 +860,15 @@ void TypePrinter::printAtomicBefore(const AtomicType *T, raw_ostream &OS) { } void TypePrinter::printAtomicAfter(const AtomicType *T, raw_ostream &OS) { } +void TypePrinter::printPipeBefore(const PipeType *T, raw_ostream &OS) { + IncludeStrongLifetimeRAII Strong(Policy); + + OS << "pipe"; + spaceBeforePlaceHolder(OS); +} + +void TypePrinter::printPipeAfter(const PipeType *T, raw_ostream &OS) { +} /// Appends the given scope to the end of a string. void TypePrinter::AppendScope(DeclContext *DC, raw_ostream &OS) { if (DC->isTranslationUnit()) return; diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp index 9ce525709cf4..1bc6c51b9b85 100644 --- a/lib/Basic/Targets.cpp +++ b/lib/Basic/Targets.cpp @@ -223,7 +223,24 @@ protected: public: DarwinTargetInfo(const llvm::Triple &Triple) : OSTargetInfo(Triple) { - this->TLSSupported = Triple.isMacOSX() && !Triple.isMacOSXVersionLT(10, 7); + // By default, no TLS, and we whitelist permitted architecture/OS + // combinations. + this->TLSSupported = false; + + if (Triple.isMacOSX()) + this->TLSSupported = !Triple.isMacOSXVersionLT(10, 7); + else if (Triple.isiOS()) { + // 64-bit iOS supported it from 8 onwards, 32-bit from 9 onwards. + if (Triple.getArch() == llvm::Triple::x86_64 || + Triple.getArch() == llvm::Triple::aarch64) + this->TLSSupported = !Triple.isOSVersionLT(8); + else if (Triple.getArch() == llvm::Triple::x86 || + Triple.getArch() == llvm::Triple::arm || + Triple.getArch() == llvm::Triple::thumb) + this->TLSSupported = !Triple.isOSVersionLT(9); + } else if (Triple.isWatchOS()) + this->TLSSupported = !Triple.isOSVersionLT(2); + this->MCountName = "\01mcount"; } @@ -7281,7 +7298,7 @@ public: explicit WebAssembly32TargetInfo(const llvm::Triple &T) : WebAssemblyTargetInfo(T) { MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32; - DataLayoutString = "e-p:32:32-i64:64-n32:64-S128"; + DataLayoutString = "e-m:e-p:32:32-i64:64-n32:64-S128"; } protected: @@ -7299,7 +7316,7 @@ public: LongAlign = LongWidth = 64; PointerAlign = PointerWidth = 64; MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64; - DataLayoutString = "e-p:64:64-i64:64-n32:64-S128"; + DataLayoutString = "e-m:e-p:64:64-i64:64-n32:64-S128"; } protected: diff --git a/lib/Basic/VirtualFileSystem.cpp b/lib/Basic/VirtualFileSystem.cpp index cf5a8d681eac..6977f400287f 100644 --- a/lib/Basic/VirtualFileSystem.cpp +++ b/lib/Basic/VirtualFileSystem.cpp @@ -658,6 +658,23 @@ directory_iterator InMemoryFileSystem::dir_begin(const Twine &Dir, EC = make_error_code(llvm::errc::not_a_directory); return directory_iterator(std::make_shared()); } + +std::error_code InMemoryFileSystem::setCurrentWorkingDirectory(const Twine &P) { + SmallString<128> Path; + P.toVector(Path); + + // Fix up relative paths. This just prepends the current working directory. + std::error_code EC = makeAbsolute(Path); + assert(!EC); + (void)EC; + + if (useNormalizedPaths()) + llvm::sys::path::remove_dots(Path, /*remove_dot_dot=*/true); + + if (!Path.empty()) + WorkingDirectory = Path.str(); + return std::error_code(); +} } } diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp index 7032d00386f3..6d746c25eed1 100644 --- a/lib/CodeGen/BackendUtil.cpp +++ b/lib/CodeGen/BackendUtil.cpp @@ -28,6 +28,7 @@ #include "llvm/IR/Module.h" #include "llvm/IR/Verifier.h" #include "llvm/MC/SubtargetFeature.h" +#include "llvm/Object/FunctionIndexObjectFile.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/TargetRegistry.h" @@ -54,7 +55,6 @@ class EmitAssemblyHelper { const clang::TargetOptions &TargetOpts; const LangOptions &LangOpts; Module *TheModule; - std::unique_ptr FunctionIndex; Timer CodeGenerationTime; @@ -97,7 +97,7 @@ private: return PerFunctionPasses; } - void CreatePasses(); + void CreatePasses(FunctionInfoIndex *FunctionIndex); /// Generates the TargetMachine. /// Returns Null if it is unable to create the target machine. @@ -117,12 +117,11 @@ private: public: EmitAssemblyHelper(DiagnosticsEngine &_Diags, const CodeGenOptions &CGOpts, const clang::TargetOptions &TOpts, - const LangOptions &LOpts, Module *M, - std::unique_ptr Index) + const LangOptions &LOpts, Module *M) : Diags(_Diags), CodeGenOpts(CGOpts), TargetOpts(TOpts), LangOpts(LOpts), - TheModule(M), FunctionIndex(std::move(Index)), - CodeGenerationTime("Code Generation Time"), CodeGenPasses(nullptr), - PerModulePasses(nullptr), PerFunctionPasses(nullptr) {} + TheModule(M), CodeGenerationTime("Code Generation Time"), + CodeGenPasses(nullptr), PerModulePasses(nullptr), + PerFunctionPasses(nullptr) {} ~EmitAssemblyHelper() { delete CodeGenPasses; @@ -278,7 +277,7 @@ static void addSymbolRewriterPass(const CodeGenOptions &Opts, MPM->add(createRewriteSymbolsPass(DL)); } -void EmitAssemblyHelper::CreatePasses() { +void EmitAssemblyHelper::CreatePasses(FunctionInfoIndex *FunctionIndex) { if (CodeGenOpts.DisableLLVMPasses) return; @@ -332,9 +331,8 @@ void EmitAssemblyHelper::CreatePasses() { // If we are performing a ThinLTO importing compile, invoke the LTO // pipeline and pass down the in-memory function index. - if (!CodeGenOpts.ThinLTOIndexFile.empty()) { - assert(FunctionIndex && "Expected non-empty function index"); - PMBuilder.FunctionIndex = FunctionIndex.get(); + if (FunctionIndex) { + PMBuilder.FunctionIndex = FunctionIndex; PMBuilder.populateLTOPassManager(*MPM); return; } @@ -642,7 +640,28 @@ void EmitAssemblyHelper::EmitAssembly(BackendAction Action, return; if (TM) TheModule->setDataLayout(TM->createDataLayout()); - CreatePasses(); + + // If we are performing a ThinLTO importing compile, load the function + // index into memory and pass it into CreatePasses, which will add it + // to the PassManagerBuilder and invoke LTO passes. + std::unique_ptr FunctionIndex; + if (!CodeGenOpts.ThinLTOIndexFile.empty()) { + ErrorOr> IndexOrErr = + llvm::getFunctionIndexForFile(CodeGenOpts.ThinLTOIndexFile, + [&](const DiagnosticInfo &DI) { + TheModule->getContext().diagnose(DI); + }); + if (std::error_code EC = IndexOrErr.getError()) { + std::string Error = EC.message(); + errs() << "Error loading index file '" << CodeGenOpts.ThinLTOIndexFile + << "': " << Error << "\n"; + return; + } + FunctionIndex = std::move(IndexOrErr.get()); + assert(FunctionIndex && "Expected non-empty function index"); + } + + CreatePasses(FunctionIndex.get()); switch (Action) { case Backend_EmitNothing: @@ -695,10 +714,8 @@ void clang::EmitBackendOutput(DiagnosticsEngine &Diags, const clang::TargetOptions &TOpts, const LangOptions &LOpts, StringRef TDesc, Module *M, BackendAction Action, - raw_pwrite_stream *OS, - std::unique_ptr Index) { - EmitAssemblyHelper AsmHelper(Diags, CGOpts, TOpts, LOpts, M, - std::move(Index)); + raw_pwrite_stream *OS) { + EmitAssemblyHelper AsmHelper(Diags, CGOpts, TOpts, LOpts, M); AsmHelper.EmitAssembly(Action, OS); diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index 78e3978e0ff9..5df85194878d 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -2025,6 +2025,11 @@ llvm::DIType *CGDebugInfo::CreateType(const AtomicType *Ty, llvm::DIFile *U) { return getOrCreateType(Ty->getValueType(), U); } +llvm::DIType* CGDebugInfo::CreateType(const PipeType *Ty, + llvm::DIFile *U) { + return getOrCreateType(Ty->getElementType(), U); +} + llvm::DIType *CGDebugInfo::CreateEnumType(const EnumType *Ty) { const EnumDecl *ED = Ty->getDecl(); @@ -2284,6 +2289,9 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) { case Type::Atomic: return CreateType(cast(Ty), Unit); + case Type::Pipe: + return CreateType(cast(Ty), Unit); + case Type::TemplateSpecialization: return CreateType(cast(Ty), Unit); diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h index 57d5c808f297..a68dd33fa5fe 100644 --- a/lib/CodeGen/CGDebugInfo.h +++ b/lib/CodeGen/CGDebugInfo.h @@ -168,6 +168,7 @@ class CGDebugInfo { llvm::DIType *CreateType(const RValueReferenceType *Ty, llvm::DIFile *Unit); llvm::DIType *CreateType(const MemberPointerType *Ty, llvm::DIFile *F); llvm::DIType *CreateType(const AtomicType *Ty, llvm::DIFile *F); + llvm::DIType *CreateType(const PipeType *Ty, llvm::DIFile *F); /// Get enumeration type. llvm::DIType *CreateEnumType(const EnumType *Ty); llvm::DIType *CreateTypeDefinition(const EnumType *Ty); diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index dabd2b1528bb..507ce3d7d0ce 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -3365,6 +3365,7 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { case CK_PointerToBoolean: case CK_VectorSplat: case CK_IntegralCast: + case CK_BooleanToSignedIntegral: case CK_IntegralToBoolean: case CK_IntegralToFloating: case CK_FloatingToIntegral: diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp index 20838db044c9..a4547a9982be 100644 --- a/lib/CodeGen/CGExprAgg.cpp +++ b/lib/CodeGen/CGExprAgg.cpp @@ -721,6 +721,7 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) { case CK_ToVoid: case CK_VectorSplat: case CK_IntegralCast: + case CK_BooleanToSignedIntegral: case CK_IntegralToBoolean: case CK_IntegralToFloating: case CK_FloatingToIntegral: diff --git a/lib/CodeGen/CGExprComplex.cpp b/lib/CodeGen/CGExprComplex.cpp index ccdb53287e9f..22910d931ded 100644 --- a/lib/CodeGen/CGExprComplex.cpp +++ b/lib/CodeGen/CGExprComplex.cpp @@ -462,6 +462,7 @@ ComplexPairTy ComplexExprEmitter::EmitCast(CastKind CK, Expr *Op, case CK_ToVoid: case CK_VectorSplat: case CK_IntegralCast: + case CK_BooleanToSignedIntegral: case CK_IntegralToBoolean: case CK_IntegralToFloating: case CK_FloatingToIntegral: diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp index 3839ab718fa3..ee049f1810a2 100644 --- a/lib/CodeGen/CGExprConstant.cpp +++ b/lib/CodeGen/CGExprConstant.cpp @@ -735,6 +735,7 @@ public: case CK_PointerToBoolean: case CK_NullToPointer: case CK_IntegralCast: + case CK_BooleanToSignedIntegral: case CK_IntegralToPointer: case CK_IntegralToBoolean: case CK_IntegralToFloating: diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index 725d96f29877..268e7967b808 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -811,14 +811,15 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType, // A scalar can be splatted to an extended vector of the same element type if (DstType->isExtVectorType() && !SrcType->isVectorType()) { - // Cast the scalar to element type - QualType EltTy = DstType->getAs()->getElementType(); - llvm::Value *Elt = EmitScalarConversion( - Src, SrcType, EltTy, Loc, CGF.getContext().getLangOpts().OpenCL); + // Sema should add casts to make sure that the source expression's type is + // the same as the vector's element type (sans qualifiers) + assert(DstType->castAs()->getElementType().getTypePtr() == + SrcType.getTypePtr() && + "Splatted expr doesn't match with vector element type?"); // Splat the element across to all elements unsigned NumElements = cast(DstTy)->getNumElements(); - return Builder.CreateVectorSplat(NumElements, Elt, "splat"); + return Builder.CreateVectorSplat(NumElements, Src, "splat"); } // Allow bitcast from vector to integer/fp of the same size. @@ -1541,15 +1542,7 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { } case CK_VectorSplat: { llvm::Type *DstTy = ConvertType(DestTy); - // Need an IgnoreImpCasts here as by default a boolean will be promoted to - // an int, which will not perform the sign extension, so if we know we are - // going to cast to a vector we have to strip the implicit cast off. - Value *Elt = Visit(const_cast(E->IgnoreImpCasts())); - Elt = EmitScalarConversion(Elt, E->IgnoreImpCasts()->getType(), - DestTy->getAs()->getElementType(), - CE->getExprLoc(), - CGF.getContext().getLangOpts().OpenCL); - + Value *Elt = Visit(const_cast(E)); // Splat the element across to all elements unsigned NumElements = cast(DstTy)->getNumElements(); return Builder.CreateVectorSplat(NumElements, Elt, "splat"); @@ -1561,6 +1554,10 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { case CK_FloatingCast: return EmitScalarConversion(Visit(E), E->getType(), DestTy, CE->getExprLoc()); + case CK_BooleanToSignedIntegral: + return EmitScalarConversion(Visit(E), E->getType(), DestTy, + CE->getExprLoc(), + /*TreatBooleanAsSigned=*/true); case CK_IntegralToBoolean: return EmitIntToBoolConversion(Visit(E)); case CK_PointerToBoolean: diff --git a/lib/CodeGen/CGOpenCLRuntime.cpp b/lib/CodeGen/CGOpenCLRuntime.cpp index 8af39ceecdfe..686678962d3e 100644 --- a/lib/CodeGen/CGOpenCLRuntime.cpp +++ b/lib/CodeGen/CGOpenCLRuntime.cpp @@ -99,3 +99,14 @@ llvm::Type *CGOpenCLRuntime::convertOpenCLSpecificType(const Type *T) { llvm::StructType::create(Ctx, "opencl.reserve_id_t"), 0); } } + +llvm::Type *CGOpenCLRuntime::getPipeType() { + if (!PipeTy){ + uint32_t PipeAddrSpc = + CGM.getContext().getTargetAddressSpace(LangAS::opencl_global); + PipeTy = llvm::PointerType::get(llvm::StructType::create( + CGM.getLLVMContext(), "opencl.pipe_t"), PipeAddrSpc); + } + + return PipeTy; +} diff --git a/lib/CodeGen/CGOpenCLRuntime.h b/lib/CodeGen/CGOpenCLRuntime.h index 0c50b92914b8..f1a7a3106443 100644 --- a/lib/CodeGen/CGOpenCLRuntime.h +++ b/lib/CodeGen/CGOpenCLRuntime.h @@ -32,9 +32,10 @@ class CodeGenModule; class CGOpenCLRuntime { protected: CodeGenModule &CGM; + llvm::Type *PipeTy; public: - CGOpenCLRuntime(CodeGenModule &CGM) : CGM(CGM) {} + CGOpenCLRuntime(CodeGenModule &CGM) : CGM(CGM), PipeTy(nullptr) {} virtual ~CGOpenCLRuntime(); /// Emit the IR required for a work-group-local variable declaration, and add @@ -44,6 +45,8 @@ public: const VarDecl &D); virtual llvm::Type *convertOpenCLSpecificType(const Type *T); + + virtual llvm::Type *getPipeType(); }; } diff --git a/lib/CodeGen/CGOpenMPRuntime.cpp b/lib/CodeGen/CGOpenMPRuntime.cpp index 6d4fc9f64b47..3b97ba2469ae 100644 --- a/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/lib/CodeGen/CGOpenMPRuntime.cpp @@ -84,7 +84,7 @@ public: protected: CGOpenMPRegionKind RegionKind; - const RegionCodeGenTy &CodeGen; + RegionCodeGenTy CodeGen; OpenMPDirectiveKind Kind; bool HasCancel; }; diff --git a/lib/CodeGen/CGOpenMPRuntime.h b/lib/CodeGen/CGOpenMPRuntime.h index 6b04fbeb09b5..b3256375d9b6 100644 --- a/lib/CodeGen/CGOpenMPRuntime.h +++ b/lib/CodeGen/CGOpenMPRuntime.h @@ -335,7 +335,7 @@ private: public: /// \brief Kind of a given entry. Currently, only target regions are /// supported. - enum OffloadingEntryInfoKinds { + enum OffloadingEntryInfoKinds : unsigned { // Entry is a target region. OFFLOAD_ENTRY_INFO_TARGET_REGION = 0, // Invalid entry info. @@ -955,7 +955,7 @@ public: /// \brief Emit the target regions enclosed in \a GD function definition or /// the function itself in case it is a valid device function. Returns true if /// \a GD was dealt with successfully. - /// \param FD Function to scan. + /// \param GD Function to scan. virtual bool emitTargetFunctions(GlobalDecl GD); /// \brief Emit the global variable if it is a valid device global variable. diff --git a/lib/CodeGen/CodeGenAction.cpp b/lib/CodeGen/CodeGenAction.cpp index abef5432518e..0a670ab19aa5 100644 --- a/lib/CodeGen/CodeGenAction.cpp +++ b/lib/CodeGen/CodeGenAction.cpp @@ -26,12 +26,10 @@ #include "llvm/IR/DebugInfo.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/DiagnosticPrinter.h" -#include "llvm/IR/FunctionInfo.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/IRReader/IRReader.h" #include "llvm/Linker/Linker.h" -#include "llvm/Object/FunctionIndexObjectFile.h" #include "llvm/Pass.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/SourceMgr.h" @@ -781,43 +779,11 @@ void CodeGenAction::ExecuteAction() { TheModule->setTargetTriple(TargetOpts.Triple); } - auto DiagHandler = [&](const DiagnosticInfo &DI) { - TheModule->getContext().diagnose(DI); - }; - - // If we are performing ThinLTO importing compilation (indicated by - // a non-empty index file option), then we need promote to global scope - // and rename any local values that are potentially exported to other - // modules. Do this early so that the rest of the compilation sees the - // promoted symbols. - std::unique_ptr Index; - if (!CI.getCodeGenOpts().ThinLTOIndexFile.empty()) { - ErrorOr> IndexOrErr = - llvm::getFunctionIndexForFile(CI.getCodeGenOpts().ThinLTOIndexFile, - DiagHandler); - if (std::error_code EC = IndexOrErr.getError()) { - std::string Error = EC.message(); - errs() << "Error loading index file '" - << CI.getCodeGenOpts().ThinLTOIndexFile << "': " << Error - << "\n"; - return; - } - Index = std::move(IndexOrErr.get()); - assert(Index); - // Currently this requires creating a new Module object. - std::unique_ptr RenamedModule = - renameModuleForThinLTO(std::move(TheModule), Index.get()); - if (!RenamedModule) - return; - - TheModule = std::move(RenamedModule); - } - LLVMContext &Ctx = TheModule->getContext(); Ctx.setInlineAsmDiagnosticHandler(BitcodeInlineAsmDiagHandler); EmitBackendOutput(CI.getDiagnostics(), CI.getCodeGenOpts(), TargetOpts, CI.getLangOpts(), CI.getTarget().getDataLayoutString(), - TheModule.get(), BA, OS, std::move(Index)); + TheModule.get(), BA, OS); return; } diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index 048a04328fc2..e38ff0a39da3 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -79,7 +79,7 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext) if (CGM.getCodeGenOpts().ReciprocalMath) { FMF.setAllowReciprocal(); } - Builder.SetFastMathFlags(FMF); + Builder.setFastMathFlags(FMF); } CodeGenFunction::~CodeGenFunction() { @@ -195,6 +195,7 @@ TypeEvaluationKind CodeGenFunction::getEvaluationKind(QualType type) { case Type::FunctionNoProto: case Type::Enum: case Type::ObjCObjectPointer: + case Type::Pipe: return TEK_Scalar; // Complexes. @@ -511,7 +512,8 @@ static void GenOpenCLArgMetadata(const FunctionDecl *FD, llvm::Function *Fn, typeQuals += typeQuals.empty() ? "volatile" : " volatile"; } else { uint32_t AddrSpc = 0; - if (ty->isImageType()) + bool isPipe = ty->isPipeType(); + if (ty->isImageType() || isPipe) AddrSpc = CGM.getContext().getTargetAddressSpace(LangAS::opencl_global); @@ -519,7 +521,11 @@ static void GenOpenCLArgMetadata(const FunctionDecl *FD, llvm::Function *Fn, llvm::ConstantAsMetadata::get(Builder.getInt32(AddrSpc))); // Get argument type name. - std::string typeName = ty.getUnqualifiedType().getAsString(Policy); + std::string typeName; + if (isPipe) + typeName = cast(ty)->getElementType().getAsString(Policy); + else + typeName = ty.getUnqualifiedType().getAsString(Policy); // Turn "unsigned type" to "utype" std::string::size_type pos = typeName.find("unsigned"); @@ -528,7 +534,12 @@ static void GenOpenCLArgMetadata(const FunctionDecl *FD, llvm::Function *Fn, argTypeNames.push_back(llvm::MDString::get(Context, typeName)); - std::string baseTypeName = + std::string baseTypeName; + if (isPipe) + baseTypeName = + cast(ty)->getElementType().getCanonicalType().getAsString(Policy); + else + baseTypeName = ty.getUnqualifiedType().getCanonicalType().getAsString(Policy); // Turn "unsigned type" to "utype" @@ -543,12 +554,16 @@ static void GenOpenCLArgMetadata(const FunctionDecl *FD, llvm::Function *Fn, typeQuals = "const"; if (ty.isVolatileQualified()) typeQuals += typeQuals.empty() ? "volatile" : " volatile"; + if (isPipe) + typeQuals = "pipe"; } argTypeQuals.push_back(llvm::MDString::get(Context, typeQuals)); - // Get image access qualifier: - if (ty->isImageType()) { + // Get image and pipe access qualifier: + // FIXME: now image and pipe share the same access qualifier maybe we can + // refine it to OpenCL access qualifier and also handle write_read + if (ty->isImageType()|| ty->isPipeType()) { const OpenCLImageAccessAttr *A = parm->getAttr(); if (A && A->isWriteOnly()) accessQuals.push_back(llvm::MDString::get(Context, "write_only")); @@ -1727,6 +1742,10 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) { case Type::Atomic: type = cast(ty)->getValueType(); break; + + case Type::Pipe: + type = cast(ty)->getElementType(); + break; } } while (type->isVariablyModifiedType()); } diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 536c55ae4e18..97b166278f81 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -615,7 +615,20 @@ void CodeGenModule::setTLSMode(llvm::GlobalValue *GV, const VarDecl &D) const { } StringRef CodeGenModule::getMangledName(GlobalDecl GD) { - StringRef &FoundStr = MangledDeclNames[GD.getCanonicalDecl()]; + GlobalDecl CanonicalGD = GD.getCanonicalDecl(); + + // Some ABIs don't have constructor variants. Make sure that base and + // complete constructors get mangled the same. + if (const auto *CD = dyn_cast(CanonicalGD.getDecl())) { + if (!getTarget().getCXXABI().hasConstructorVariants()) { + CXXCtorType OrigCtorType = GD.getCtorType(); + assert(OrigCtorType == Ctor_Base || OrigCtorType == Ctor_Complete); + if (OrigCtorType == Ctor_Base) + CanonicalGD = GlobalDecl(CD, Ctor_Complete); + } + } + + StringRef &FoundStr = MangledDeclNames[CanonicalGD]; if (!FoundStr.empty()) return FoundStr; diff --git a/lib/CodeGen/CodeGenPGO.cpp b/lib/CodeGen/CodeGenPGO.cpp index 5ae861eab0d3..2c0d93b394ac 100644 --- a/lib/CodeGen/CodeGenPGO.cpp +++ b/lib/CodeGen/CodeGenPGO.cpp @@ -699,7 +699,7 @@ CodeGenPGO::emitEmptyCounterMapping(const Decl *D, StringRef Name, setFuncName(Name, Linkage); CGM.getCoverageMapping()->addFunctionMappingRecord( - FuncNameVar, FuncName, FunctionHash, CoverageMapping); + FuncNameVar, FuncName, FunctionHash, CoverageMapping, false); } void CodeGenPGO::computeRegionCounts(const Decl *D) { diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp index fcda05320551..09d9bf17b3bf 100644 --- a/lib/CodeGen/CodeGenTypes.cpp +++ b/lib/CodeGen/CodeGenTypes.cpp @@ -628,6 +628,10 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) { } break; } + case Type::Pipe: { + ResultType = CGM.getOpenCLRuntime().getPipeType(); + break; + } } assert(ResultType && "Didn't convert a type?"); diff --git a/lib/CodeGen/CoverageMappingGen.cpp b/lib/CodeGen/CoverageMappingGen.cpp index 1d4d7099e194..03e22cd398aa 100644 --- a/lib/CodeGen/CoverageMappingGen.cpp +++ b/lib/CodeGen/CoverageMappingGen.cpp @@ -910,11 +910,11 @@ static void dump(llvm::raw_ostream &OS, StringRef FunctionName, } void CoverageMappingModuleGen::addFunctionMappingRecord( - llvm::GlobalVariable *NamePtr, StringRef NameValue, - uint64_t FuncHash, const std::string &CoverageMapping) { + llvm::GlobalVariable *NamePtr, StringRef NameValue, uint64_t FuncHash, + const std::string &CoverageMapping, bool isUsed) { llvm::LLVMContext &Ctx = CGM.getLLVMContext(); if (!FunctionRecordTy) { - #define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) LLVMType, +#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) LLVMType, llvm::Type *FunctionRecordTypes[] = { #include "llvm/ProfileData/InstrProfData.inc" }; @@ -929,6 +929,9 @@ void CoverageMappingModuleGen::addFunctionMappingRecord( }; FunctionRecords.push_back(llvm::ConstantStruct::get( FunctionRecordTy, makeArrayRef(FunctionRecordVals))); + if (!isUsed) + FunctionNames.push_back( + llvm::ConstantExpr::getBitCast(NamePtr, llvm::Type::getInt8PtrTy(Ctx))); CoverageMappings += CoverageMapping; if (CGM.getCodeGenOpts().DumpCoverageMapping) { @@ -1023,6 +1026,17 @@ void CoverageMappingModuleGen::emit() { // Make sure the data doesn't get deleted. CGM.addUsedGlobal(CovData); + // Create the deferred function records array + if (!FunctionNames.empty()) { + auto NamesArrTy = llvm::ArrayType::get(llvm::Type::getInt8PtrTy(Ctx), + FunctionNames.size()); + auto NamesArrVal = llvm::ConstantArray::get(NamesArrTy, FunctionNames); + // This variable will *NOT* be emitted to the object file. It is used + // to pass the list of names referenced to codegen. + new llvm::GlobalVariable(CGM.getModule(), NamesArrTy, true, + llvm::GlobalValue::InternalLinkage, NamesArrVal, + llvm::getCoverageNamesVarName()); + } } unsigned CoverageMappingModuleGen::getFileID(const FileEntry *File) { diff --git a/lib/CodeGen/CoverageMappingGen.h b/lib/CodeGen/CoverageMappingGen.h index 0d1bf6d975c9..9ae2bcffe4ca 100644 --- a/lib/CodeGen/CoverageMappingGen.h +++ b/lib/CodeGen/CoverageMappingGen.h @@ -54,6 +54,7 @@ class CoverageMappingModuleGen { CoverageSourceInfo &SourceInfo; llvm::SmallDenseMap FileEntries; std::vector FunctionRecords; + std::vector FunctionNames; llvm::StructType *FunctionRecordTy; std::string CoverageMappings; @@ -70,7 +71,8 @@ public: void addFunctionMappingRecord(llvm::GlobalVariable *FunctionName, StringRef FunctionNameValue, uint64_t FunctionHash, - const std::string &CoverageMapping); + const std::string &CoverageMapping, + bool isUsed = true); /// \brief Emit the coverage mapping data for a translation unit. void emit(); diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp index 0c4008f8ee78..e02c8dc3a86a 100644 --- a/lib/CodeGen/ItaniumCXXABI.cpp +++ b/lib/CodeGen/ItaniumCXXABI.cpp @@ -2715,6 +2715,9 @@ void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty) { case Type::Auto: llvm_unreachable("Undeduced auto type shouldn't get here"); + case Type::Pipe: + llvm_unreachable("Pipe types shouldn't get here"); + case Type::Builtin: // GCC treats vector and complex types as fundamental types. case Type::Vector: @@ -2939,6 +2942,9 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty, bool Force) { case Type::Auto: llvm_unreachable("Undeduced auto type shouldn't get here"); + case Type::Pipe: + llvm_unreachable("Pipe type shouldn't get here"); + case Type::ConstantArray: case Type::IncompleteArray: case Type::VariableArray: diff --git a/lib/CodeGen/ObjectFilePCHContainerOperations.cpp b/lib/CodeGen/ObjectFilePCHContainerOperations.cpp index b397eb352a60..f385e53fa01f 100644 --- a/lib/CodeGen/ObjectFilePCHContainerOperations.cpp +++ b/lib/CodeGen/ObjectFilePCHContainerOperations.cpp @@ -59,8 +59,10 @@ class PCHContainerGenerator : public ASTConsumer { struct DebugTypeVisitor : public RecursiveASTVisitor { clang::CodeGen::CGDebugInfo &DI; ASTContext &Ctx; - DebugTypeVisitor(clang::CodeGen::CGDebugInfo &DI, ASTContext &Ctx) - : DI(DI), Ctx(Ctx) {} + bool SkipTagDecls; + DebugTypeVisitor(clang::CodeGen::CGDebugInfo &DI, ASTContext &Ctx, + bool SkipTagDecls) + : DI(DI), Ctx(Ctx), SkipTagDecls(SkipTagDecls) {} /// Determine whether this type can be represented in DWARF. static bool CanRepresent(const Type *Ty) { @@ -75,6 +77,12 @@ class PCHContainerGenerator : public ASTConsumer { } bool VisitTypeDecl(TypeDecl *D) { + // TagDecls may be deferred until after all decls have been merged and we + // know the complete type. Pure forward declarations will be skipped, but + // they don't need to be emitted into the module anyway. + if (SkipTagDecls && isa(D)) + return true; + QualType QualTy = Ctx.getTypeDeclType(D); if (!QualTy.isNull() && CanRepresent(QualTy.getTypePtr())) DI.getOrCreateStandaloneType(QualTy, D->getLocation()); @@ -165,7 +173,7 @@ public: // Collect debug info for all decls in this group. for (auto *I : D) if (!I->isFromASTFile()) { - DebugTypeVisitor DTV(*Builder->getModuleDebugInfo(), *Ctx); + DebugTypeVisitor DTV(*Builder->getModuleDebugInfo(), *Ctx, true); DTV.TraverseDecl(I); } return true; @@ -179,6 +187,11 @@ public: if (Diags.hasErrorOccurred()) return; + if (D->isFromASTFile()) + return; + + DebugTypeVisitor DTV(*Builder->getModuleDebugInfo(), *Ctx, false); + DTV.TraverseDecl(D); Builder->UpdateCompletedType(D); } diff --git a/lib/Driver/Action.cpp b/lib/Driver/Action.cpp index 49dccd224bff..e9490e96db8d 100644 --- a/lib/Driver/Action.cpp +++ b/lib/Driver/Action.cpp @@ -8,17 +8,14 @@ //===----------------------------------------------------------------------===// #include "clang/Driver/Action.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Regex.h" #include using namespace clang::driver; using namespace llvm::opt; -Action::~Action() { - if (OwnsInputs) { - for (iterator it = begin(), ie = end(); it != ie; ++it) - delete *it; - } -} +Action::~Action() {} const char *Action::getClassName(ActionClass AC) { switch (AC) { @@ -51,33 +48,53 @@ InputAction::InputAction(const Arg &_Input, types::ID _Type) void BindArchAction::anchor() {} -BindArchAction::BindArchAction(std::unique_ptr Input, - const char *_ArchName) - : Action(BindArchClass, std::move(Input)), ArchName(_ArchName) {} +BindArchAction::BindArchAction(Action *Input, const char *_ArchName) + : Action(BindArchClass, Input), ArchName(_ArchName) {} + +// Converts CUDA GPU architecture, e.g. "sm_21", to its corresponding virtual +// compute arch, e.g. "compute_20". Returns null if the input arch is null or +// doesn't match an existing arch. +static const char* GpuArchToComputeName(const char *ArchName) { + if (!ArchName) + return nullptr; + return llvm::StringSwitch(ArchName) + .Cases("sm_20", "sm_21", "compute_20") + .Case("sm_30", "compute_30") + .Case("sm_32", "compute_32") + .Case("sm_35", "compute_35") + .Case("sm_37", "compute_37") + .Case("sm_50", "compute_50") + .Case("sm_52", "compute_52") + .Case("sm_53", "compute_53") + .Default(nullptr); +} void CudaDeviceAction::anchor() {} -CudaDeviceAction::CudaDeviceAction(std::unique_ptr Input, - const char *ArchName, bool AtTopLevel) - : Action(CudaDeviceClass, std::move(Input)), GpuArchName(ArchName), - AtTopLevel(AtTopLevel) {} - -void CudaHostAction::anchor() {} +CudaDeviceAction::CudaDeviceAction(Action *Input, const char *ArchName, + bool AtTopLevel) + : Action(CudaDeviceClass, Input), GpuArchName(ArchName), + AtTopLevel(AtTopLevel) { + assert(IsValidGpuArchName(GpuArchName)); +} -CudaHostAction::CudaHostAction(std::unique_ptr Input, - const ActionList &DeviceActions) - : Action(CudaHostClass, std::move(Input)), DeviceActions(DeviceActions) {} +const char *CudaDeviceAction::getComputeArchName() const { + return GpuArchToComputeName(GpuArchName); +} -CudaHostAction::~CudaHostAction() { - for (auto &DA : DeviceActions) - delete DA; +bool CudaDeviceAction::IsValidGpuArchName(llvm::StringRef ArchName) { + return GpuArchToComputeName(ArchName.data()) != nullptr; } +void CudaHostAction::anchor() {} + +CudaHostAction::CudaHostAction(Action *Input, const ActionList &DeviceActions) + : Action(CudaHostClass, Input), DeviceActions(DeviceActions) {} + void JobAction::anchor() {} -JobAction::JobAction(ActionClass Kind, std::unique_ptr Input, - types::ID Type) - : Action(Kind, std::move(Input), Type) {} +JobAction::JobAction(ActionClass Kind, Action *Input, types::ID Type) + : Action(Kind, Input, Type) {} JobAction::JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type) : Action(Kind, Inputs, Type) { @@ -85,45 +102,38 @@ JobAction::JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type) void PreprocessJobAction::anchor() {} -PreprocessJobAction::PreprocessJobAction(std::unique_ptr Input, - types::ID OutputType) - : JobAction(PreprocessJobClass, std::move(Input), OutputType) {} +PreprocessJobAction::PreprocessJobAction(Action *Input, types::ID OutputType) + : JobAction(PreprocessJobClass, Input, OutputType) {} void PrecompileJobAction::anchor() {} -PrecompileJobAction::PrecompileJobAction(std::unique_ptr Input, - types::ID OutputType) - : JobAction(PrecompileJobClass, std::move(Input), OutputType) {} +PrecompileJobAction::PrecompileJobAction(Action *Input, types::ID OutputType) + : JobAction(PrecompileJobClass, Input, OutputType) {} void AnalyzeJobAction::anchor() {} -AnalyzeJobAction::AnalyzeJobAction(std::unique_ptr Input, - types::ID OutputType) - : JobAction(AnalyzeJobClass, std::move(Input), OutputType) {} +AnalyzeJobAction::AnalyzeJobAction(Action *Input, types::ID OutputType) + : JobAction(AnalyzeJobClass, Input, OutputType) {} void MigrateJobAction::anchor() {} -MigrateJobAction::MigrateJobAction(std::unique_ptr Input, - types::ID OutputType) - : JobAction(MigrateJobClass, std::move(Input), OutputType) {} +MigrateJobAction::MigrateJobAction(Action *Input, types::ID OutputType) + : JobAction(MigrateJobClass, Input, OutputType) {} void CompileJobAction::anchor() {} -CompileJobAction::CompileJobAction(std::unique_ptr Input, - types::ID OutputType) - : JobAction(CompileJobClass, std::move(Input), OutputType) {} +CompileJobAction::CompileJobAction(Action *Input, types::ID OutputType) + : JobAction(CompileJobClass, Input, OutputType) {} void BackendJobAction::anchor() {} -BackendJobAction::BackendJobAction(std::unique_ptr Input, - types::ID OutputType) - : JobAction(BackendJobClass, std::move(Input), OutputType) {} +BackendJobAction::BackendJobAction(Action *Input, types::ID OutputType) + : JobAction(BackendJobClass, Input, OutputType) {} void AssembleJobAction::anchor() {} -AssembleJobAction::AssembleJobAction(std::unique_ptr Input, - types::ID OutputType) - : JobAction(AssembleJobClass, std::move(Input), OutputType) {} +AssembleJobAction::AssembleJobAction(Action *Input, types::ID OutputType) + : JobAction(AssembleJobClass, Input, OutputType) {} void LinkJobAction::anchor() {} @@ -145,21 +155,20 @@ DsymutilJobAction::DsymutilJobAction(ActionList &Inputs, types::ID Type) void VerifyJobAction::anchor() {} -VerifyJobAction::VerifyJobAction(ActionClass Kind, - std::unique_ptr Input, types::ID Type) - : JobAction(Kind, std::move(Input), Type) { +VerifyJobAction::VerifyJobAction(ActionClass Kind, Action *Input, + types::ID Type) + : JobAction(Kind, Input, Type) { assert((Kind == VerifyDebugInfoJobClass || Kind == VerifyPCHJobClass) && "ActionClass is not a valid VerifyJobAction"); } void VerifyDebugInfoJobAction::anchor() {} -VerifyDebugInfoJobAction::VerifyDebugInfoJobAction( - std::unique_ptr Input, types::ID Type) - : VerifyJobAction(VerifyDebugInfoJobClass, std::move(Input), Type) {} +VerifyDebugInfoJobAction::VerifyDebugInfoJobAction(Action *Input, + types::ID Type) + : VerifyJobAction(VerifyDebugInfoJobClass, Input, Type) {} void VerifyPCHJobAction::anchor() {} -VerifyPCHJobAction::VerifyPCHJobAction(std::unique_ptr Input, - types::ID Type) - : VerifyJobAction(VerifyPCHJobClass, std::move(Input), Type) {} +VerifyPCHJobAction::VerifyPCHJobAction(Action *Input, types::ID Type) + : VerifyJobAction(VerifyPCHJobClass, Input, Type) {} diff --git a/lib/Driver/Compilation.cpp b/lib/Driver/Compilation.cpp index e4af2a6ced8a..1c2eecd3ccc5 100644 --- a/lib/Driver/Compilation.cpp +++ b/lib/Driver/Compilation.cpp @@ -40,11 +40,6 @@ Compilation::~Compilation() { if (it->second != TranslatedArgs) delete it->second; - // Free the actions, if built. - for (ActionList::iterator it = Actions.begin(), ie = Actions.end(); - it != ie; ++it) - delete *it; - // Free redirections of stdout/stderr. if (Redirects) { delete Redirects[1]; @@ -208,7 +203,8 @@ void Compilation::initCompilationForDiagnostics() { ForDiagnostics = true; // Free actions and jobs. - DeleteContainerPointers(Actions); + Actions.clear(); + AllActions.clear(); Jobs.clear(); // Clear temporary/results file lists. diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index 85bbcb4113ab..1e0a48d52928 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -1049,19 +1049,15 @@ void Driver::BuildUniversalActions(Compilation &C, const ToolChain &TC, << types::getTypeName(Act->getType()); ActionList Inputs; - for (unsigned i = 0, e = Archs.size(); i != e; ++i) { - Inputs.push_back( - new BindArchAction(std::unique_ptr(Act), Archs[i])); - if (i != 0) - Inputs.back()->setOwnsInputs(false); - } + for (unsigned i = 0, e = Archs.size(); i != e; ++i) + Inputs.push_back(C.MakeAction(Act, Archs[i])); // Lipo if necessary, we do it this way because we need to set the arch flag // so that -Xarch_ gets overwritten. if (Inputs.size() == 1 || Act->getType() == types::TY_Nothing) Actions.append(Inputs.begin(), Inputs.end()); else - Actions.push_back(new LipoJobAction(Inputs, Act->getType())); + Actions.push_back(C.MakeAction(Inputs, Act->getType())); // Handle debug info queries. Arg *A = Args.getLastArg(options::OPT_g_Group); @@ -1077,15 +1073,16 @@ void Driver::BuildUniversalActions(Compilation &C, const ToolChain &TC, ActionList Inputs; Inputs.push_back(Actions.back()); Actions.pop_back(); - Actions.push_back(new DsymutilJobAction(Inputs, types::TY_dSYM)); + Actions.push_back( + C.MakeAction(Inputs, types::TY_dSYM)); } // Verify the debug info output. if (Args.hasArg(options::OPT_verify_debug_info)) { - std::unique_ptr VerifyInput(Actions.back()); + Action* LastAction = Actions.back(); Actions.pop_back(); - Actions.push_back(new VerifyDebugInfoJobAction(std::move(VerifyInput), - types::TY_Nothing)); + Actions.push_back(C.MakeAction( + LastAction, types::TY_Nothing)); } } } @@ -1283,26 +1280,29 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args, // Actions and /p Current is released. Otherwise the function creates // and returns a new CudaHostAction which wraps /p Current and device // side actions. -static std::unique_ptr -buildCudaActions(Compilation &C, DerivedArgList &Args, const Arg *InputArg, - std::unique_ptr HostAction, ActionList &Actions) { +static Action *buildCudaActions(Compilation &C, DerivedArgList &Args, + const Arg *InputArg, Action *HostAction, + ActionList &Actions) { Arg *PartialCompilationArg = Args.getLastArg(options::OPT_cuda_host_only, options::OPT_cuda_device_only); // Host-only compilation case. if (PartialCompilationArg && PartialCompilationArg->getOption().matches(options::OPT_cuda_host_only)) - return std::unique_ptr( - new CudaHostAction(std::move(HostAction), {})); + return C.MakeAction(HostAction, ActionList()); // Collect all cuda_gpu_arch parameters, removing duplicates. SmallVector GpuArchList; llvm::StringSet<> GpuArchNames; for (Arg *A : Args) { - if (A->getOption().matches(options::OPT_cuda_gpu_arch_EQ)) { - A->claim(); - if (GpuArchNames.insert(A->getValue()).second) - GpuArchList.push_back(A->getValue()); - } + if (!A->getOption().matches(options::OPT_cuda_gpu_arch_EQ)) + continue; + A->claim(); + + const auto& Arch = A->getValue(); + if (!CudaDeviceAction::IsValidGpuArchName(Arch)) + C.getDriver().Diag(clang::diag::err_drv_cuda_bad_gpu_arch) << Arch; + else if (GpuArchNames.insert(Arch).second) + GpuArchList.push_back(Arch); } // Default to sm_20 which is the lowest common denominator for supported GPUs. @@ -1325,13 +1325,10 @@ buildCudaActions(Compilation &C, DerivedArgList &Args, const Arg *InputArg, "Failed to create actions for all devices"); // Check whether any of device actions stopped before they could generate PTX. - bool PartialCompilation = false; - for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) { - if (CudaDeviceActions[I]->getKind() != Action::BackendJobClass) { - PartialCompilation = true; - break; - } - } + bool PartialCompilation = + llvm::any_of(CudaDeviceActions, [](const Action *a) { + return a->getKind() != Action::BackendJobClass; + }); // Figure out what to do with device actions -- pass them as inputs to the // host action or run each of them independently. @@ -1350,12 +1347,12 @@ buildCudaActions(Compilation &C, DerivedArgList &Args, const Arg *InputArg, } for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) - Actions.push_back(new CudaDeviceAction( - std::unique_ptr(CudaDeviceActions[I]), GpuArchList[I], - /* AtTopLevel */ true)); + Actions.push_back(C.MakeAction(CudaDeviceActions[I], + GpuArchList[I], + /* AtTopLevel */ true)); // Kill host action in case of device-only compilation. if (DeviceOnlyCompilation) - HostAction.reset(nullptr); + return nullptr; return HostAction; } @@ -1363,13 +1360,12 @@ buildCudaActions(Compilation &C, DerivedArgList &Args, const Arg *InputArg, // with AtTopLevel=false and become inputs for the host action. ActionList DeviceActions; for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) - DeviceActions.push_back(new CudaDeviceAction( - std::unique_ptr(CudaDeviceActions[I]), GpuArchList[I], - /* AtTopLevel */ false)); + DeviceActions.push_back( + C.MakeAction(CudaDeviceActions[I], GpuArchList[I], + /* AtTopLevel */ false)); // Return a new host action that incorporates original host action and all // device actions. - return std::unique_ptr( - new CudaHostAction(std::move(HostAction), DeviceActions)); + return C.MakeAction(HostAction, DeviceActions); } void Driver::BuildActions(Compilation &C, const ToolChain &TC, @@ -1470,15 +1466,14 @@ void Driver::BuildActions(Compilation &C, const ToolChain &TC, continue; } - phases::ID CudaInjectionPhase = FinalPhase; - for (const auto &Phase : PL) - if (Phase <= FinalPhase && Phase == phases::Compile) { - CudaInjectionPhase = Phase; - break; - } + phases::ID CudaInjectionPhase = + (phases::Compile < FinalPhase && + llvm::find(PL, phases::Compile) != PL.end()) + ? phases::Compile + : FinalPhase; // Build the pipeline for this file. - std::unique_ptr Current(new InputAction(*InputArg, InputType)); + Action *Current = C.MakeAction(*InputArg, InputType); for (SmallVectorImpl::iterator i = PL.begin(), e = PL.end(); i != e; ++i) { phases::ID Phase = *i; @@ -1490,7 +1485,8 @@ void Driver::BuildActions(Compilation &C, const ToolChain &TC, // Queue linker inputs. if (Phase == phases::Link) { assert((i + 1) == e && "linking must be final compilation step."); - LinkerInputs.push_back(Current.release()); + LinkerInputs.push_back(Current); + Current = nullptr; break; } @@ -1501,11 +1497,10 @@ void Driver::BuildActions(Compilation &C, const ToolChain &TC, continue; // Otherwise construct the appropriate action. - Current = ConstructPhaseAction(TC, Args, Phase, std::move(Current)); + Current = ConstructPhaseAction(C, TC, Args, Phase, Current); if (InputType == types::TY_CUDA && Phase == CudaInjectionPhase) { - Current = - buildCudaActions(C, Args, InputArg, std::move(Current), Actions); + Current = buildCudaActions(C, Args, InputArg, Current, Actions); if (!Current) break; } @@ -1516,12 +1511,13 @@ void Driver::BuildActions(Compilation &C, const ToolChain &TC, // If we ended with something, add to the output list. if (Current) - Actions.push_back(Current.release()); + Actions.push_back(Current); } // Add a link action if necessary. if (!LinkerInputs.empty()) - Actions.push_back(new LinkJobAction(LinkerInputs, types::TY_Image)); + Actions.push_back( + C.MakeAction(LinkerInputs, types::TY_Image)); // If we are linking, claim any options which are obviously only used for // compilation. @@ -1538,10 +1534,9 @@ void Driver::BuildActions(Compilation &C, const ToolChain &TC, Args.ClaimAllArgs(options::OPT_cuda_host_only); } -std::unique_ptr -Driver::ConstructPhaseAction(const ToolChain &TC, const ArgList &Args, - phases::ID Phase, - std::unique_ptr Input) const { +Action *Driver::ConstructPhaseAction(Compilation &C, const ToolChain &TC, + const ArgList &Args, phases::ID Phase, + Action *Input) const { llvm::PrettyStackTraceString CrashInfo("Constructing phase actions"); // Build the appropriate action. switch (Phase) { @@ -1561,7 +1556,7 @@ Driver::ConstructPhaseAction(const ToolChain &TC, const ArgList &Args, assert(OutputTy != types::TY_INVALID && "Cannot preprocess this input type!"); } - return llvm::make_unique(std::move(Input), OutputTy); + return C.MakeAction(Input, OutputTy); } case phases::Precompile: { types::ID OutputTy = types::TY_PCH; @@ -1569,53 +1564,43 @@ Driver::ConstructPhaseAction(const ToolChain &TC, const ArgList &Args, // Syntax checks should not emit a PCH file OutputTy = types::TY_Nothing; } - return llvm::make_unique(std::move(Input), OutputTy); + return C.MakeAction(Input, OutputTy); } case phases::Compile: { if (Args.hasArg(options::OPT_fsyntax_only)) - return llvm::make_unique(std::move(Input), - types::TY_Nothing); + return C.MakeAction(Input, types::TY_Nothing); if (Args.hasArg(options::OPT_rewrite_objc)) - return llvm::make_unique(std::move(Input), - types::TY_RewrittenObjC); + return C.MakeAction(Input, types::TY_RewrittenObjC); if (Args.hasArg(options::OPT_rewrite_legacy_objc)) - return llvm::make_unique(std::move(Input), - types::TY_RewrittenLegacyObjC); + return C.MakeAction(Input, + types::TY_RewrittenLegacyObjC); if (Args.hasArg(options::OPT__analyze, options::OPT__analyze_auto)) - return llvm::make_unique(std::move(Input), - types::TY_Plist); + return C.MakeAction(Input, types::TY_Plist); if (Args.hasArg(options::OPT__migrate)) - return llvm::make_unique(std::move(Input), - types::TY_Remap); + return C.MakeAction(Input, types::TY_Remap); if (Args.hasArg(options::OPT_emit_ast)) - return llvm::make_unique(std::move(Input), - types::TY_AST); + return C.MakeAction(Input, types::TY_AST); if (Args.hasArg(options::OPT_module_file_info)) - return llvm::make_unique(std::move(Input), - types::TY_ModuleFile); + return C.MakeAction(Input, types::TY_ModuleFile); if (Args.hasArg(options::OPT_verify_pch)) - return llvm::make_unique(std::move(Input), - types::TY_Nothing); - return llvm::make_unique(std::move(Input), - types::TY_LLVM_BC); + return C.MakeAction(Input, types::TY_Nothing); + return C.MakeAction(Input, types::TY_LLVM_BC); } case phases::Backend: { if (isUsingLTO()) { types::ID Output = Args.hasArg(options::OPT_S) ? types::TY_LTO_IR : types::TY_LTO_BC; - return llvm::make_unique(std::move(Input), Output); + return C.MakeAction(Input, Output); } if (Args.hasArg(options::OPT_emit_llvm)) { types::ID Output = Args.hasArg(options::OPT_S) ? types::TY_LLVM_IR : types::TY_LLVM_BC; - return llvm::make_unique(std::move(Input), Output); + return C.MakeAction(Input, Output); } - return llvm::make_unique(std::move(Input), - types::TY_PP_Asm); + return C.MakeAction(Input, types::TY_PP_Asm); } case phases::Assemble: - return llvm::make_unique(std::move(Input), - types::TY_Object); + return C.MakeAction(Input, types::TY_Object); } llvm_unreachable("invalid phase in ConstructPhaseAction"); @@ -1662,12 +1647,11 @@ void Driver::BuildJobs(Compilation &C) const { LinkingOutput = getDefaultImageName(); } - InputInfo II; BuildJobsForAction(C, A, &C.getDefaultToolChain(), /*BoundArch*/ nullptr, /*AtTopLevel*/ true, /*MultipleArchs*/ ArchNames.size() > 1, - /*LinkingOutput*/ LinkingOutput, II); + /*LinkingOutput*/ LinkingOutput); } // If the user passed -Qunused-arguments or there were errors, don't warn @@ -1795,21 +1779,19 @@ static const Tool *selectToolForJob(Compilation &C, bool SaveTemps, return ToolForJob; } -void Driver::BuildJobsForAction(Compilation &C, const Action *A, - const ToolChain *TC, const char *BoundArch, - bool AtTopLevel, bool MultipleArchs, - const char *LinkingOutput, - InputInfo &Result) const { +InputInfo Driver::BuildJobsForAction(Compilation &C, const Action *A, + const ToolChain *TC, const char *BoundArch, + bool AtTopLevel, bool MultipleArchs, + const char *LinkingOutput) const { llvm::PrettyStackTraceString CrashInfo("Building compilation jobs"); InputInfoList CudaDeviceInputInfos; if (const CudaHostAction *CHA = dyn_cast(A)) { - InputInfo II; // Append outputs of device jobs to the input list. for (const Action *DA : CHA->getDeviceActions()) { - BuildJobsForAction(C, DA, TC, nullptr, AtTopLevel, - /*MultipleArchs*/ false, LinkingOutput, II); - CudaDeviceInputInfos.push_back(II); + CudaDeviceInputInfos.push_back( + BuildJobsForAction(C, DA, TC, nullptr, AtTopLevel, + /*MultipleArchs*/ false, LinkingOutput)); } // Override current action with a real host compile action and continue // processing it. @@ -1823,11 +1805,9 @@ void Driver::BuildJobsForAction(Compilation &C, const Action *A, Input.claim(); if (Input.getOption().matches(options::OPT_INPUT)) { const char *Name = Input.getValue(); - Result = InputInfo(Name, A->getType(), Name); - } else { - Result = InputInfo(&Input, A->getType(), ""); + return InputInfo(A, Name, /* BaseInput = */ Name); } - return; + return InputInfo(A, &Input, /* BaseInput = */ ""); } if (const BindArchAction *BAA = dyn_cast(A)) { @@ -1841,19 +1821,17 @@ void Driver::BuildJobsForAction(Compilation &C, const Action *A, else TC = &C.getDefaultToolChain(); - BuildJobsForAction(C, *BAA->begin(), TC, ArchName, AtTopLevel, - MultipleArchs, LinkingOutput, Result); - return; + return BuildJobsForAction(C, *BAA->begin(), TC, ArchName, AtTopLevel, + MultipleArchs, LinkingOutput); } if (const CudaDeviceAction *CDA = dyn_cast(A)) { // Initial processing of CudaDeviceAction carries host params. // Call BuildJobsForAction() again, now with correct device parameters. assert(CDA->getGpuArchName() && "No GPU name in device action."); - BuildJobsForAction(C, *CDA->begin(), C.getCudaDeviceToolChain(), - CDA->getGpuArchName(), CDA->isAtTopLevel(), - /*MultipleArchs*/ true, LinkingOutput, Result); - return; + return BuildJobsForAction(C, *CDA->begin(), C.getCudaDeviceToolChain(), + CDA->getGpuArchName(), CDA->isAtTopLevel(), + /*MultipleArchs*/ true, LinkingOutput); } const ActionList *Inputs = &A->getInputs(); @@ -1863,16 +1841,15 @@ void Driver::BuildJobsForAction(Compilation &C, const Action *A, const Tool *T = selectToolForJob(C, isSaveTempsEnabled(), TC, JA, Inputs, CollapsedCHA); if (!T) - return; + return InputInfo(); // If we've collapsed action list that contained CudaHostAction we // need to build jobs for device-side inputs it may have held. if (CollapsedCHA) { - InputInfo II; for (const Action *DA : CollapsedCHA->getDeviceActions()) { - BuildJobsForAction(C, DA, TC, "", AtTopLevel, - /*MultipleArchs*/ false, LinkingOutput, II); - CudaDeviceInputInfos.push_back(II); + CudaDeviceInputInfos.push_back( + BuildJobsForAction(C, DA, TC, "", AtTopLevel, + /*MultipleArchs*/ false, LinkingOutput)); } } @@ -1882,14 +1859,11 @@ void Driver::BuildJobsForAction(Compilation &C, const Action *A, // Treat dsymutil and verify sub-jobs as being at the top-level too, they // shouldn't get temporary output names. // FIXME: Clean this up. - bool SubJobAtTopLevel = false; - if (AtTopLevel && (isa(A) || isa(A))) - SubJobAtTopLevel = true; - - InputInfo II; - BuildJobsForAction(C, Input, TC, BoundArch, SubJobAtTopLevel, MultipleArchs, - LinkingOutput, II); - InputInfos.push_back(II); + bool SubJobAtTopLevel = + AtTopLevel && (isa(A) || isa(A)); + InputInfos.push_back(BuildJobsForAction(C, Input, TC, BoundArch, + SubJobAtTopLevel, MultipleArchs, + LinkingOutput)); } // Always use the first input as the base input. @@ -1905,12 +1879,13 @@ void Driver::BuildJobsForAction(Compilation &C, const Action *A, InputInfos.append(CudaDeviceInputInfos.begin(), CudaDeviceInputInfos.end()); // Determine the place to write output to, if any. + InputInfo Result; if (JA->getType() == types::TY_Nothing) - Result = InputInfo(A->getType(), BaseInput); + Result = InputInfo(A, BaseInput); else - Result = InputInfo(GetNamedOutputPath(C, *JA, BaseInput, BoundArch, - AtTopLevel, MultipleArchs), - A->getType(), BaseInput); + Result = InputInfo(A, GetNamedOutputPath(C, *JA, BaseInput, BoundArch, + AtTopLevel, MultipleArchs), + BaseInput); if (CCCPrintBindings && !CCGenDiagnostics) { llvm::errs() << "# \"" << T->getToolChain().getTripleString() << '"' @@ -1925,6 +1900,7 @@ void Driver::BuildJobsForAction(Compilation &C, const Action *A, T->ConstructJob(C, *JA, Result, InputInfos, C.getArgsForToolChain(TC, BoundArch), LinkingOutput); } + return Result; } const char *Driver::getDefaultImageName() const { diff --git a/lib/Driver/InputInfo.h b/lib/Driver/InputInfo.h index b23ba575b65e..0c36e817c135 100644 --- a/lib/Driver/InputInfo.h +++ b/lib/Driver/InputInfo.h @@ -10,6 +10,7 @@ #ifndef LLVM_CLANG_LIB_DRIVER_INPUTINFO_H #define LLVM_CLANG_LIB_DRIVER_INPUTINFO_H +#include "clang/Driver/Action.h" #include "clang/Driver/Types.h" #include "llvm/Option/Arg.h" #include @@ -38,21 +39,36 @@ class InputInfo { const llvm::opt::Arg *InputArg; } Data; Class Kind; + const Action* Act; types::ID Type; const char *BaseInput; + static types::ID GetActionType(const Action *A) { + return A != nullptr ? A->getType() : types::TY_Nothing; + } + public: - InputInfo() {} - InputInfo(types::ID _Type, const char *_BaseInput) - : Kind(Nothing), Type(_Type), BaseInput(_BaseInput) { + InputInfo() : InputInfo(nullptr, nullptr) {} + InputInfo(const Action *A, const char *_BaseInput) + : Kind(Nothing), Act(A), Type(GetActionType(A)), BaseInput(_BaseInput) {} + + InputInfo(types::ID _Type, const char *_Filename, const char *_BaseInput) + : Kind(Filename), Act(nullptr), Type(_Type), BaseInput(_BaseInput) { + Data.Filename = _Filename; } - InputInfo(const char *_Filename, types::ID _Type, const char *_BaseInput) - : Kind(Filename), Type(_Type), BaseInput(_BaseInput) { + InputInfo(const Action *A, const char *_Filename, const char *_BaseInput) + : Kind(Filename), Act(A), Type(GetActionType(A)), BaseInput(_BaseInput) { Data.Filename = _Filename; } - InputInfo(const llvm::opt::Arg *_InputArg, types::ID _Type, + + InputInfo(types::ID _Type, const llvm::opt::Arg *_InputArg, + const char *_BaseInput) + : Kind(InputArg), Act(nullptr), Type(_Type), BaseInput(_BaseInput) { + Data.InputArg = _InputArg; + } + InputInfo(const Action *A, const llvm::opt::Arg *_InputArg, const char *_BaseInput) - : Kind(InputArg), Type(_Type), BaseInput(_BaseInput) { + : Kind(InputArg), Act(A), Type(GetActionType(A)), BaseInput(_BaseInput) { Data.InputArg = _InputArg; } @@ -61,6 +77,9 @@ public: bool isInputArg() const { return Kind == InputArg; } types::ID getType() const { return Type; } const char *getBaseInput() const { return BaseInput; } + /// The action for which this InputInfo was created. May be null. + const Action *getAction() const { return Act; } + void setAction(const Action *A) { Act = A; } const char *getFilename() const { assert(isFilename() && "Invalid accessor."); diff --git a/lib/Driver/MSVCToolChain.cpp b/lib/Driver/MSVCToolChain.cpp index b7e576e53e8f..68747155b81c 100644 --- a/lib/Driver/MSVCToolChain.cpp +++ b/lib/Driver/MSVCToolChain.cpp @@ -634,6 +634,96 @@ SanitizerMask MSVCToolChain::getSupportedSanitizers() const { return Res; } +static void TranslateOptArg(Arg *A, llvm::opt::DerivedArgList &DAL, + bool SupportsForcingFramePointer, + const char *ExpandChar, const OptTable &Opts) { + assert(A->getOption().matches(options::OPT__SLASH_O)); + + StringRef OptStr = A->getValue(); + for (size_t I = 0, E = OptStr.size(); I != E; ++I) { + const char &OptChar = *(OptStr.data() + I); + switch (OptChar) { + default: + break; + case '1': + case '2': + case 'x': + case 'd': + if (&OptChar == ExpandChar) { + if (OptChar == 'd') { + DAL.AddFlagArg(A, Opts.getOption(options::OPT_O0)); + } else { + if (OptChar == '1') { + DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "s"); + } else if (OptChar == '2' || OptChar == 'x') { + DAL.AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin)); + DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "2"); + } + if (SupportsForcingFramePointer) + DAL.AddFlagArg(A, + Opts.getOption(options::OPT_fomit_frame_pointer)); + if (OptChar == '1' || OptChar == '2') + DAL.AddFlagArg(A, + Opts.getOption(options::OPT_ffunction_sections)); + } + } + break; + case 'b': + if (I + 1 != E && isdigit(OptStr[I + 1])) + ++I; + break; + case 'g': + break; + case 'i': + if (I + 1 != E && OptStr[I + 1] == '-') { + ++I; + DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_builtin)); + } else { + DAL.AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin)); + } + break; + case 's': + DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "s"); + break; + case 't': + DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "2"); + break; + case 'y': { + bool OmitFramePointer = true; + if (I + 1 != E && OptStr[I + 1] == '-') { + OmitFramePointer = false; + ++I; + } + if (SupportsForcingFramePointer) { + if (OmitFramePointer) + DAL.AddFlagArg(A, + Opts.getOption(options::OPT_fomit_frame_pointer)); + else + DAL.AddFlagArg( + A, Opts.getOption(options::OPT_fno_omit_frame_pointer)); + } + break; + } + } + } +} + +static void TranslateDArg(Arg *A, llvm::opt::DerivedArgList &DAL, + const OptTable &Opts) { + assert(A->getOption().matches(options::OPT_D)); + + StringRef Val = A->getValue(); + size_t Hash = Val.find('#'); + if (Hash == StringRef::npos || Hash > Val.find('=')) { + DAL.append(A); + return; + } + + std::string NewVal = Val; + NewVal[Hash] = '='; + DAL.AddJoinedArg(A, Opts.getOption(options::OPT_D), NewVal); +} + llvm::opt::DerivedArgList * MSVCToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args, const char *BoundArch) const { @@ -664,81 +754,18 @@ MSVCToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args, } } - // The -O flag actually takes an amalgam of other options. For example, - // '/Ogyb2' is equivalent to '/Og' '/Oy' '/Ob2'. for (Arg *A : Args) { - if (!A->getOption().matches(options::OPT__SLASH_O)) { + if (A->getOption().matches(options::OPT__SLASH_O)) { + // The -O flag actually takes an amalgam of other options. For example, + // '/Ogyb2' is equivalent to '/Og' '/Oy' '/Ob2'. + TranslateOptArg(A, *DAL, SupportsForcingFramePointer, ExpandChar, Opts); + } else if (A->getOption().matches(options::OPT_D)) { + // Translate -Dfoo#bar into -Dfoo=bar. + TranslateDArg(A, *DAL, Opts); + } else { DAL->append(A); - continue; - } - - StringRef OptStr = A->getValue(); - for (size_t I = 0, E = OptStr.size(); I != E; ++I) { - const char &OptChar = *(OptStr.data() + I); - switch (OptChar) { - default: - break; - case '1': - case '2': - case 'x': - case 'd': - if (&OptChar == ExpandChar) { - if (OptChar == 'd') { - DAL->AddFlagArg(A, Opts.getOption(options::OPT_O0)); - } else { - if (OptChar == '1') { - DAL->AddJoinedArg(A, Opts.getOption(options::OPT_O), "s"); - } else if (OptChar == '2' || OptChar == 'x') { - DAL->AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin)); - DAL->AddJoinedArg(A, Opts.getOption(options::OPT_O), "2"); - } - if (SupportsForcingFramePointer) - DAL->AddFlagArg(A, - Opts.getOption(options::OPT_fomit_frame_pointer)); - if (OptChar == '1' || OptChar == '2') - DAL->AddFlagArg(A, - Opts.getOption(options::OPT_ffunction_sections)); - } - } - break; - case 'b': - if (I + 1 != E && isdigit(OptStr[I + 1])) - ++I; - break; - case 'g': - break; - case 'i': - if (I + 1 != E && OptStr[I + 1] == '-') { - ++I; - DAL->AddFlagArg(A, Opts.getOption(options::OPT_fno_builtin)); - } else { - DAL->AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin)); - } - break; - case 's': - DAL->AddJoinedArg(A, Opts.getOption(options::OPT_O), "s"); - break; - case 't': - DAL->AddJoinedArg(A, Opts.getOption(options::OPT_O), "2"); - break; - case 'y': { - bool OmitFramePointer = true; - if (I + 1 != E && OptStr[I + 1] == '-') { - OmitFramePointer = false; - ++I; - } - if (SupportsForcingFramePointer) { - if (OmitFramePointer) - DAL->AddFlagArg(A, - Opts.getOption(options::OPT_fomit_frame_pointer)); - else - DAL->AddFlagArg( - A, Opts.getOption(options::OPT_fno_omit_frame_pointer)); - } - break; - } - } } } + return DAL; } diff --git a/lib/Driver/MinGWToolChain.cpp b/lib/Driver/MinGWToolChain.cpp index c5287bb41575..938440b08f60 100644 --- a/lib/Driver/MinGWToolChain.cpp +++ b/lib/Driver/MinGWToolChain.cpp @@ -66,17 +66,23 @@ MinGW::MinGW(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) : ToolChain(D, Triple, Args) { getProgramPaths().push_back(getDriver().getInstalledDir()); - // On Windows if there is no sysroot we search for gcc on the PATH. - if (getDriver().SysRoot.size()) - Base = getDriver().SysRoot; +// In Windows there aren't any standard install locations, we search +// for gcc on the PATH. In Linux the base is always /usr. #ifdef LLVM_ON_WIN32 + if (getDriver().SysRoot.size()) + Base = getDriver().SysRoot; else if (llvm::ErrorOr GPPName = llvm::sys::findProgramByName("gcc")) Base = llvm::sys::path::parent_path( llvm::sys::path::parent_path(GPPName.get())); -#endif - if (!Base.size()) + else Base = llvm::sys::path::parent_path(getDriver().getInstalledDir()); +#else + if (getDriver().SysRoot.size()) + Base = getDriver().SysRoot; + else + Base = "/usr"; +#endif Base += llvm::sys::path::get_separator(); findGccLibDir(); diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index 7ece3216297f..beede2e05804 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -526,7 +526,7 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { // no environment variable defined, see if we can set the default based // on -isysroot. if (OSXTarget.empty() && iOSTarget.empty() && WatchOSTarget.empty() && - Args.hasArg(options::OPT_isysroot)) { + TvOSTarget.empty() && Args.hasArg(options::OPT_isysroot)) { if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) { StringRef isysroot = A->getValue(); // Assume SDK has path: SOME_PATH/SDKs/PlatformXX.YY.sdk @@ -2716,13 +2716,8 @@ const StringRef HexagonToolChain::GetDefaultCPU() { const StringRef HexagonToolChain::GetTargetCPUVersion(const ArgList &Args) { Arg *CpuArg = nullptr; - - for (auto &A : Args) { - if (A->getOption().matches(options::OPT_mcpu_EQ)) { - CpuArg = A; - A->claim(); - } - } + if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ, options::OPT_march_EQ)) + CpuArg = A; StringRef CPU = CpuArg ? CpuArg->getValue() : GetDefaultCPU(); if (CPU.startswith("hexagon")) diff --git a/lib/Driver/ToolChains.h b/lib/Driver/ToolChains.h index f4b6b1529b30..b6fd42696ed4 100644 --- a/lib/Driver/ToolChains.h +++ b/lib/Driver/ToolChains.h @@ -730,9 +730,6 @@ public: // Until dtrace (via CTF) and LLDB can deal with distributed debug info, // FreeBSD defaults to standalone/full debug info. bool GetDefaultStandaloneDebug() const override { return true; } - llvm::DebuggerKind getDefaultDebuggerTuning() const override { - return llvm::DebuggerKind::LLDB; - } protected: Tool *buildAssembler() const override; diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index 84681053dd1a..5a2dbd388fc1 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -2069,6 +2069,16 @@ void Clang::AddHexagonTargetArgs(const ArgList &Args, CmdArgs.push_back("-machine-sink-split=0"); } +void Clang::AddWebAssemblyTargetArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { + // Default to "hidden" visibility. + if (!Args.hasArg(options::OPT_fvisibility_EQ, + options::OPT_fvisibility_ms_compat)) { + CmdArgs.push_back("-fvisibility"); + CmdArgs.push_back("hidden"); + } +} + // Decode AArch64 features from string like +[no]featureA+[no]featureB+... static bool DecodeAArch64Features(const Driver &D, StringRef text, std::vector &Features) { @@ -2970,7 +2980,7 @@ static void SplitDebugInfo(const ToolChain &TC, Compilation &C, const Tool &T, ExtractArgs.push_back(OutFile); const char *Exec = Args.MakeArgString(TC.GetProgramPath("objcopy")); - InputInfo II(Output.getFilename(), types::TY_Object, Output.getFilename()); + InputInfo II(types::TY_Object, Output.getFilename(), Output.getFilename()); // First extract the dwo sections. C.addCommand(llvm::make_unique(JA, T, Exec, ExtractArgs, II)); @@ -3253,8 +3263,9 @@ ParsePICArgs(const ToolChain &ToolChain, const llvm::Triple &Triple, // ToolChain.getTriple() and Triple? bool PIE = ToolChain.isPIEDefault(); bool PIC = PIE || ToolChain.isPICDefault(); - // The Darwin default to use PIC does not apply when using -static. - if (ToolChain.getTriple().isOSDarwin() && Args.hasArg(options::OPT_static)) + // The Darwin/MachO default to use PIC does not apply when using -static. + if (ToolChain.getTriple().isOSBinFormatMachO() && + Args.hasArg(options::OPT_static)) PIE = PIC = false; bool IsPICLevelTwo = PIC; @@ -4015,6 +4026,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, case llvm::Triple::hexagon: AddHexagonTargetArgs(Args, CmdArgs); break; + + case llvm::Triple::wasm32: + case llvm::Triple::wasm64: + AddWebAssemblyTargetArgs(Args, CmdArgs); + break; } // The 'g' groups options involve a somewhat intricate sequence of decisions @@ -4176,8 +4192,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-generate-type-units"); } - // CloudABI uses -ffunction-sections and -fdata-sections by default. - bool UseSeparateSections = Triple.getOS() == llvm::Triple::CloudABI; + // CloudABI and WebAssembly use -ffunction-sections and -fdata-sections by + // default. + bool UseSeparateSections = Triple.getOS() == llvm::Triple::CloudABI || + Triple.getArch() == llvm::Triple::wasm32 || + Triple.getArch() == llvm::Triple::wasm64; if (Args.hasFlag(options::OPT_ffunction_sections, options::OPT_fno_function_sections, UseSeparateSections)) { @@ -6040,8 +6059,7 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, // doesn't handle that so rather than warning about unused flags that are // actually used, we'll lie by omission instead. // FIXME: Stop lying and consume only the appropriate driver flags - for (const Arg *A : Args.filtered(options::OPT_W_Group)) - A->claim(); + Args.ClaimAllArgs(options::OPT_W_Group); CollectArgsForIntegratedAssembler(C, Args, CmdArgs, getToolChain().getDriver()); @@ -6078,6 +6096,12 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA, for (const auto &A : Args) { if (forwardToGCC(A->getOption())) { + // It is unfortunate that we have to claim here, as this means + // we will basically never report anything interesting for + // platforms using a generic gcc, even if we are just using gcc + // to get to the assembler. + A->claim(); + // Don't forward any -g arguments to assembly steps. if (isa(JA) && A->getOption().matches(options::OPT_g_Group)) @@ -6088,11 +6112,6 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA, A->getOption().matches(options::OPT_W_Group)) continue; - // It is unfortunate that we have to claim here, as this means - // we will basically never report anything interesting for - // platforms using a generic gcc, even if we are just using gcc - // to get to the assembler. - A->claim(); A->render(Args, CmdArgs); } } @@ -6502,10 +6521,6 @@ void amdgpu::Linker::ConstructJob(Compilation &C, const JobAction &JA, std::string Linker = getToolChain().GetProgramPath(getShortName()); ArgStringList CmdArgs; - CmdArgs.push_back("-flavor"); - CmdArgs.push_back("old-gnu"); - CmdArgs.push_back("-target"); - CmdArgs.push_back(Args.MakeArgString(getToolChain().getTripleString())); AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); @@ -6534,6 +6549,14 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA, ArgStringList CmdArgs; CmdArgs.push_back("-flavor"); CmdArgs.push_back("ld"); + + // Enable garbage collection of unused input sections by default, since code + // size is of particular importance. This is significantly facilitated by + // the enabling of -ffunction-sections and -fdata-sections in + // Clang::ConstructJob. + if (areOptimizationsEnabled(Args)) + CmdArgs.push_back("--gc-sections"); + AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); @@ -8965,7 +8988,7 @@ void nacltools::AssemblerARM::ConstructJob(Compilation &C, const JobAction &JA, const char *LinkingOutput) const { const toolchains::NaClToolChain &ToolChain = static_cast(getToolChain()); - InputInfo NaClMacros(ToolChain.GetNaClArmMacrosPath(), types::TY_PP_Asm, + InputInfo NaClMacros(types::TY_PP_Asm, ToolChain.GetNaClArmMacrosPath(), "nacl-arm-macros.s"); InputInfoList NewInputs; NewInputs.push_back(NaClMacros); diff --git a/lib/Driver/Tools.h b/lib/Driver/Tools.h index 168662f7e7fe..2b137f4a6d0b 100644 --- a/lib/Driver/Tools.h +++ b/lib/Driver/Tools.h @@ -82,6 +82,8 @@ private: llvm::opt::ArgStringList &CmdArgs) const; void AddHexagonTargetArgs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const; + void AddWebAssemblyTargetArgs(const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs) const; enum RewriteKind { RK_None, RK_Fragile, RK_NonFragile }; @@ -238,7 +240,7 @@ namespace amdgpu { class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool { public: - Linker(const ToolChain &TC) : GnuTool("amdgpu::Linker", "lld", TC) {} + Linker(const ToolChain &TC) : GnuTool("amdgpu::Linker", "ld.lld", TC) {} bool isLinkJob() const override { return true; } bool hasIntegratedCPP() const override { return false; } void ConstructJob(Compilation &C, const JobAction &JA, diff --git a/lib/Edit/RewriteObjCFoundationAPI.cpp b/lib/Edit/RewriteObjCFoundationAPI.cpp index 9f71168de8fc..482c0f6f8568 100644 --- a/lib/Edit/RewriteObjCFoundationAPI.cpp +++ b/lib/Edit/RewriteObjCFoundationAPI.cpp @@ -1077,6 +1077,9 @@ static bool rewriteToNumericBoxedExpression(const ObjCMessageExpr *Msg, case CK_BuiltinFnToFnPtr: case CK_ZeroToOCLEvent: return false; + + case CK_BooleanToSignedIntegral: + llvm_unreachable("OpenCL-specific cast in Objective-C?"); } } diff --git a/lib/Format/ContinuationIndenter.cpp b/lib/Format/ContinuationIndenter.cpp index 8faab2869de6..11183355f73a 100644 --- a/lib/Format/ContinuationIndenter.cpp +++ b/lib/Format/ContinuationIndenter.cpp @@ -150,7 +150,12 @@ bool ContinuationIndenter::mustBreak(const LineState &State) { if (Previous.is(tok::semi) && State.LineContainsContinuedForLoopSection) return true; if ((startsNextParameter(Current, Style) || Previous.is(tok::semi) || - (Previous.is(TT_TemplateCloser) && Current.is(TT_StartOfName)) || + (Previous.is(TT_TemplateCloser) && Current.is(TT_StartOfName) && + // FIXME: This is a temporary workaround for the case where clang-format + // sets BreakBeforeParameter to avoid bin packing and this creates a + // completely unnecessary line break after a template type that isn't + // line-wrapped. + (Previous.NestingLevel == 1 || Style.BinPackParameters)) || (Style.BreakBeforeTernaryOperators && Current.is(TT_ConditionalExpr) && Previous.isNot(tok::question)) || (!Style.BreakBeforeTernaryOperators && @@ -177,13 +182,15 @@ bool ContinuationIndenter::mustBreak(const LineState &State) { return true; unsigned NewLineColumn = getNewLineColumn(State); - if (State.Column <= NewLineColumn) - return false; - if (Current.isMemberAccess() && - State.Column + getLengthToNextOperator(Current) > Style.ColumnLimit) + State.Column + getLengthToNextOperator(Current) > Style.ColumnLimit && + (State.Column > NewLineColumn || + Current.NestingLevel < State.StartOfLineLevel)) return true; + if (State.Column <= NewLineColumn) + return false; + if (Style.AlwaysBreakBeforeMultilineStrings && (NewLineColumn == State.FirstIndent + Style.ContinuationIndentWidth || Previous.is(tok::comma) || Current.NestingLevel < 2) && @@ -383,7 +390,8 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun, State.Stack.back().LastSpace = State.Column; State.Stack.back().NestedBlockIndent = State.Column; } else if (!Current.isOneOf(tok::comment, tok::caret) && - (Previous.is(tok::comma) || + ((Previous.is(tok::comma) && + !Previous.is(TT_OverloadedOperator)) || (Previous.is(tok::colon) && Previous.is(TT_ObjCMethodExpr)))) { State.Stack.back().LastSpace = State.Column; } else if ((Previous.isOneOf(TT_BinaryOperator, TT_ConditionalExpr, @@ -860,7 +868,7 @@ void ContinuationIndenter::moveStatePastFakeLParens(LineState &State, (!SkipFirstExtraIndent && *I > prec::Assignment && !Current.isTrailingComment())) NewParenState.Indent += Style.ContinuationIndentWidth; - if ((Previous && !Previous->opensScope()) || *I > prec::Comma) + if ((Previous && !Previous->opensScope()) || *I != prec::Comma) NewParenState.BreakBeforeParameter = false; State.Stack.push_back(NewParenState); SkipFirstExtraIndent = false; @@ -906,8 +914,12 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State, NewIndent = State.Stack.back().LastSpace + Style.ContinuationIndentWidth; } const FormatToken *NextNoComment = Current.getNextNonComment(); + bool EndsInComma = Current.MatchingParen && + Current.MatchingParen->Previous && + Current.MatchingParen->Previous->is(tok::comma); AvoidBinPacking = - Current.isOneOf(TT_ArrayInitializerLSquare, TT_DictLiteral) || + (Current.is(TT_ArrayInitializerLSquare) && EndsInComma) || + Current.is(TT_DictLiteral) || Style.Language == FormatStyle::LK_Proto || !Style.BinPackArguments || (NextNoComment && NextNoComment->is(TT_DesignatedInitializerPeriod)); if (Current.ParameterCount > 1) diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp index 5068fca5c44d..2689368da513 100644 --- a/lib/Format/Format.cpp +++ b/lib/Format/Format.cpp @@ -583,6 +583,7 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) { GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; GoogleStyle.BreakBeforeTernaryOperators = false; + GoogleStyle.CommentPragmas = "@(export|visibility) {"; GoogleStyle.MaxEmptyLinesToKeep = 3; GoogleStyle.SpacesInContainerLiterals = false; } else if (Language == FormatStyle::LK_Proto) { @@ -1238,6 +1239,8 @@ private: FormatTok->Type = TT_ImplicitStringLiteral; break; } + if (FormatTok->Type == TT_ImplicitStringLiteral) + break; } if (FormatTok->is(TT_ImplicitStringLiteral)) @@ -1901,8 +1904,9 @@ tooling::Replacements reformat(const FormatStyle &Style, StringRef Code, IntrusiveRefCntPtr(new DiagnosticIDs), new DiagnosticOptions); SourceManager SourceMgr(Diagnostics, Files); - InMemoryFileSystem->addFile(FileName, 0, - llvm::MemoryBuffer::getMemBuffer(Code, FileName)); + InMemoryFileSystem->addFile( + FileName, 0, llvm::MemoryBuffer::getMemBuffer( + Code, FileName, /*RequiresNullTerminator=*/false)); FileID ID = SourceMgr.createFileID(Files.getFile(FileName), SourceLocation(), clang::SrcMgr::C_User); SourceLocation StartOfFile = SourceMgr.getLocForStartOfFile(ID); diff --git a/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp index caff1312f300..8fbb43b7996d 100644 --- a/lib/Format/TokenAnnotator.cpp +++ b/lib/Format/TokenAnnotator.cpp @@ -119,7 +119,9 @@ private: } } - if (Left->Previous && + if (Left->is(TT_OverloadedOperatorLParen)) { + Contexts.back().IsExpression = false; + } else if (Left->Previous && (Left->Previous->isOneOf(tok::kw_static_assert, tok::kw_decltype, tok::kw_if, tok::kw_while, tok::l_paren, tok::comma) || @@ -132,9 +134,7 @@ private: // This is a parameter list of a lambda expression. Contexts.back().IsExpression = false; } else if (Line.InPPDirective && - (!Left->Previous || - !Left->Previous->isOneOf(tok::identifier, - TT_OverloadedOperator))) { + (!Left->Previous || !Left->Previous->is(tok::identifier))) { Contexts.back().IsExpression = true; } else if (Contexts[Contexts.size() - 2].CaretFound) { // This is the parameter list of an ObjC block. @@ -199,6 +199,18 @@ private: Left->MatchingParen = CurrentToken; CurrentToken->MatchingParen = Left; + if (CurrentToken->Next && CurrentToken->Next->is(tok::l_brace) && + Left->Previous && Left->Previous->is(tok::l_paren)) { + // Detect the case where macros are used to generate lambdas or + // function bodies, e.g.: + // auto my_lambda = MARCO((Type *type, int i) { .. body .. }); + for (FormatToken *Tok = Left; Tok != CurrentToken; Tok = Tok->Next) { + if (Tok->is(TT_BinaryOperator) && + Tok->isOneOf(tok::star, tok::amp, tok::ampamp)) + Tok->Type = TT_PointerOrReference; + } + } + if (StartsObjCMethodExpr) { CurrentToken->Type = TT_ObjCMethodExpr; if (Contexts.back().FirstObjCSelectorName) { @@ -568,7 +580,8 @@ private: if (CurrentToken->isOneOf(tok::star, tok::amp)) CurrentToken->Type = TT_PointerOrReference; consumeToken(); - if (CurrentToken && CurrentToken->Previous->is(TT_BinaryOperator)) + if (CurrentToken && + CurrentToken->Previous->isOneOf(TT_BinaryOperator, tok::comma)) CurrentToken->Previous->Type = TT_OverloadedOperator; } if (CurrentToken) { @@ -1713,7 +1726,7 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line, if (Right.is(Keywords.kw_function) && Left.isNot(tok::comma)) return 100; if (Left.is(TT_JsTypeColon)) - return 100; + return 35; } if (Left.is(tok::comma) || (Right.is(tok::identifier) && Right.Next && @@ -2058,14 +2071,14 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line, if (Right.isOneOf(TT_TrailingReturnArrow, TT_LambdaArrow) || Left.isOneOf(TT_TrailingReturnArrow, TT_LambdaArrow)) return true; + if (Right.is(TT_OverloadedOperatorLParen)) + return Style.SpaceBeforeParens == FormatStyle::SBPO_Always; if (Left.is(tok::comma)) return true; if (Right.is(tok::comma)) return false; if (Right.isOneOf(TT_CtorInitializerColon, TT_ObjCBlockLParen)) return true; - if (Right.is(TT_OverloadedOperatorLParen)) - return Style.SpaceBeforeParens == FormatStyle::SBPO_Always; if (Right.is(tok::colon)) { if (Line.First->isOneOf(tok::kw_case, tok::kw_default) || !Right.getNextNonComment() || Right.getNextNonComment()->is(tok::semi)) diff --git a/lib/Format/UnwrappedLineParser.cpp b/lib/Format/UnwrappedLineParser.cpp index 94b849881941..7b8f6e652416 100644 --- a/lib/Format/UnwrappedLineParser.cpp +++ b/lib/Format/UnwrappedLineParser.cpp @@ -315,6 +315,7 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) { // definitions, too. unsigned StoredPosition = Tokens->getPosition(); FormatToken *Tok = FormatTok; + const FormatToken *PrevTok = getPreviousToken(); // Keep a stack of positions of lbrace tokens. We will // update information about whether an lbrace starts a // braced init list or a different block during the loop. @@ -331,47 +332,53 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) { switch (Tok->Tok.getKind()) { case tok::l_brace: - Tok->BlockKind = BK_Unknown; + if (Style.Language == FormatStyle::LK_JavaScript && PrevTok && + PrevTok->is(tok::colon)) + // In TypeScript's TypeMemberLists, there can be semicolons between the + // individual members. + Tok->BlockKind = BK_BracedInit; + else + Tok->BlockKind = BK_Unknown; LBraceStack.push_back(Tok); break; case tok::r_brace: - if (!LBraceStack.empty()) { - if (LBraceStack.back()->BlockKind == BK_Unknown) { - bool ProbablyBracedList = false; - if (Style.Language == FormatStyle::LK_Proto) { - ProbablyBracedList = NextTok->isOneOf(tok::comma, tok::r_square); - } else { - // Using OriginalColumn to distinguish between ObjC methods and - // binary operators is a bit hacky. - bool NextIsObjCMethod = NextTok->isOneOf(tok::plus, tok::minus) && - NextTok->OriginalColumn == 0; - - // If there is a comma, semicolon or right paren after the closing - // brace, we assume this is a braced initializer list. Note that - // regardless how we mark inner braces here, we will overwrite the - // BlockKind later if we parse a braced list (where all blocks - // inside are by default braced lists), or when we explicitly detect - // blocks (for example while parsing lambdas). - // - // We exclude + and - as they can be ObjC visibility modifiers. - ProbablyBracedList = - NextTok->isOneOf(tok::comma, tok::period, tok::colon, - tok::r_paren, tok::r_square, tok::l_brace, - tok::l_square, tok::l_paren, tok::ellipsis) || - (NextTok->is(tok::semi) && - (!ExpectClassBody || LBraceStack.size() != 1)) || - (NextTok->isBinaryOperator() && !NextIsObjCMethod); - } - if (ProbablyBracedList) { - Tok->BlockKind = BK_BracedInit; - LBraceStack.back()->BlockKind = BK_BracedInit; - } else { - Tok->BlockKind = BK_Block; - LBraceStack.back()->BlockKind = BK_Block; - } + if (LBraceStack.empty()) + break; + if (LBraceStack.back()->BlockKind == BK_Unknown) { + bool ProbablyBracedList = false; + if (Style.Language == FormatStyle::LK_Proto) { + ProbablyBracedList = NextTok->isOneOf(tok::comma, tok::r_square); + } else { + // Using OriginalColumn to distinguish between ObjC methods and + // binary operators is a bit hacky. + bool NextIsObjCMethod = NextTok->isOneOf(tok::plus, tok::minus) && + NextTok->OriginalColumn == 0; + + // If there is a comma, semicolon or right paren after the closing + // brace, we assume this is a braced initializer list. Note that + // regardless how we mark inner braces here, we will overwrite the + // BlockKind later if we parse a braced list (where all blocks + // inside are by default braced lists), or when we explicitly detect + // blocks (for example while parsing lambdas). + // + // We exclude + and - as they can be ObjC visibility modifiers. + ProbablyBracedList = + NextTok->isOneOf(tok::comma, tok::period, tok::colon, + tok::r_paren, tok::r_square, tok::l_brace, + tok::l_square, tok::l_paren, tok::ellipsis) || + (NextTok->is(tok::semi) && + (!ExpectClassBody || LBraceStack.size() != 1)) || + (NextTok->isBinaryOperator() && !NextIsObjCMethod); + } + if (ProbablyBracedList) { + Tok->BlockKind = BK_BracedInit; + LBraceStack.back()->BlockKind = BK_BracedInit; + } else { + Tok->BlockKind = BK_Block; + LBraceStack.back()->BlockKind = BK_Block; } - LBraceStack.pop_back(); } + LBraceStack.pop_back(); break; case tok::at: case tok::semi: @@ -381,14 +388,16 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) { case tok::kw_switch: case tok::kw_try: case tok::kw___try: - if (!LBraceStack.empty()) + if (!LBraceStack.empty() && LBraceStack.back()->BlockKind == BK_Unknown) LBraceStack.back()->BlockKind = BK_Block; break; default: break; } + PrevTok = Tok; Tok = NextTok; } while (Tok->Tok.isNot(tok::eof) && !LBraceStack.empty()); + // Assume other blocks for all unclosed opening braces. for (unsigned i = 0, e = LBraceStack.size(); i != e; ++i) { if (LBraceStack[i]->BlockKind == BK_Unknown) @@ -841,6 +850,8 @@ void UnwrappedLineParser::parseStructuralElement() { // This does not apply for Java and JavaScript. if (Style.Language == FormatStyle::LK_Java || Style.Language == FormatStyle::LK_JavaScript) { + if (FormatTok->is(tok::semi)) + nextToken(); addUnwrappedLine(); return; } @@ -986,13 +997,11 @@ bool UnwrappedLineParser::tryToParseLambda() { nextToken(); return false; } - // FIXME: This is a dirty way to access the previous token. Find a better - // solution. - if (!Line->Tokens.empty() && - (Line->Tokens.back().Tok->isOneOf(tok::identifier, tok::kw_operator, - tok::kw_new, tok::kw_delete) || - Line->Tokens.back().Tok->closesScope() || - Line->Tokens.back().Tok->isSimpleTypeSpecifier())) { + const FormatToken* Previous = getPreviousToken(); + if (Previous && + (Previous->isOneOf(tok::identifier, tok::kw_operator, tok::kw_new, + tok::kw_delete) || + Previous->closesScope() || Previous->isSimpleTypeSpecifier())) { nextToken(); return false; } @@ -1174,6 +1183,14 @@ bool UnwrappedLineParser::parseBracedList(bool ContinueOnSemicolons) { 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 + // used for error recovery if we have otherwise determined that this is + // a braced list. + if (Style.Language == FormatStyle::LK_JavaScript) { + nextToken(); + break; + } HasError = true; if (!ContinueOnSemicolons) return !HasError; @@ -1792,18 +1809,22 @@ void UnwrappedLineParser::parseJavaScriptEs6ImportExport() { return; } + // Consume the "abstract" in "export abstract class". + if (FormatTok->is(Keywords.kw_abstract)) + nextToken(); + if (FormatTok->isOneOf(tok::kw_const, tok::kw_class, tok::kw_enum, - Keywords.kw_let, Keywords.kw_var)) + Keywords.kw_interface, Keywords.kw_let, + Keywords.kw_var)) return; // Fall through to parsing the corresponding structure. - if (FormatTok->is(tok::l_brace)) { - FormatTok->BlockKind = BK_Block; - parseBracedList(); - } - - while (!eof() && FormatTok->isNot(tok::semi) && - FormatTok->isNot(tok::l_brace)) { - nextToken(); + while (!eof() && FormatTok->isNot(tok::semi)) { + if (FormatTok->is(tok::l_brace)) { + FormatTok->BlockKind = BK_Block; + parseBracedList(); + } else { + nextToken(); + } } } @@ -1877,6 +1898,14 @@ void UnwrappedLineParser::nextToken() { readToken(); } +const FormatToken *UnwrappedLineParser::getPreviousToken() { + // FIXME: This is a dirty way to access the previous token. Find a better + // solution. + if (!Line || Line->Tokens.empty()) + return nullptr; + return Line->Tokens.back().Tok; +} + void UnwrappedLineParser::readToken() { bool CommentsInCurrentLine = true; do { diff --git a/lib/Format/UnwrappedLineParser.h b/lib/Format/UnwrappedLineParser.h index a13c03f94086..6d40ab4f3120 100644 --- a/lib/Format/UnwrappedLineParser.h +++ b/lib/Format/UnwrappedLineParser.h @@ -110,6 +110,7 @@ private: void addUnwrappedLine(); bool eof() const; void nextToken(); + const FormatToken *getPreviousToken(); void readToken(); void flushComments(bool NewlineBeforeNext); void pushToken(FormatToken *Tok); diff --git a/lib/Format/WhitespaceManager.cpp b/lib/Format/WhitespaceManager.cpp index 725f05bcd8fc..d6e6ed2c2baa 100644 --- a/lib/Format/WhitespaceManager.cpp +++ b/lib/Format/WhitespaceManager.cpp @@ -30,7 +30,7 @@ WhitespaceManager::Change::Change( unsigned IndentLevel, int Spaces, unsigned StartOfTokenColumn, unsigned NewlinesBefore, StringRef PreviousLinePostfix, StringRef CurrentLinePrefix, tok::TokenKind Kind, bool ContinuesPPDirective, - bool IsStartOfDeclName) + bool IsStartOfDeclName, bool IsInsideToken) : CreateReplacement(CreateReplacement), OriginalWhitespaceRange(OriginalWhitespaceRange), StartOfTokenColumn(StartOfTokenColumn), NewlinesBefore(NewlinesBefore), @@ -38,8 +38,8 @@ WhitespaceManager::Change::Change( CurrentLinePrefix(CurrentLinePrefix), Kind(Kind), ContinuesPPDirective(ContinuesPPDirective), IsStartOfDeclName(IsStartOfDeclName), IndentLevel(IndentLevel), - Spaces(Spaces), IsTrailingComment(false), TokenLength(0), - PreviousEndOfTokenColumn(0), EscapedNewlineColumn(0), + Spaces(Spaces), IsInsideToken(IsInsideToken), IsTrailingComment(false), + TokenLength(0), PreviousEndOfTokenColumn(0), EscapedNewlineColumn(0), StartOfBlockComment(nullptr), IndentationOffset(0) {} void WhitespaceManager::reset() { @@ -55,20 +55,23 @@ void WhitespaceManager::replaceWhitespace(FormatToken &Tok, unsigned Newlines, return; Tok.Decision = (Newlines > 0) ? FD_Break : FD_Continue; Changes.push_back( - Change(true, Tok.WhitespaceRange, IndentLevel, Spaces, StartOfTokenColumn, - Newlines, "", "", Tok.Tok.getKind(), InPPDirective && !Tok.IsFirst, - Tok.is(TT_StartOfName) || Tok.is(TT_FunctionDeclarationName))); + Change(/*CreateReplacement=*/true, Tok.WhitespaceRange, IndentLevel, + Spaces, StartOfTokenColumn, Newlines, "", "", Tok.Tok.getKind(), + InPPDirective && !Tok.IsFirst, + Tok.is(TT_StartOfName) || Tok.is(TT_FunctionDeclarationName), + /*IsInsideToken=*/false)); } void WhitespaceManager::addUntouchableToken(const FormatToken &Tok, bool InPPDirective) { if (Tok.Finalized) return; - Changes.push_back( - Change(false, Tok.WhitespaceRange, /*IndentLevel=*/0, - /*Spaces=*/0, Tok.OriginalColumn, Tok.NewlinesBefore, "", "", - Tok.Tok.getKind(), InPPDirective && !Tok.IsFirst, - Tok.is(TT_StartOfName) || Tok.is(TT_FunctionDeclarationName))); + Changes.push_back(Change( + /*CreateReplacement=*/false, Tok.WhitespaceRange, /*IndentLevel=*/0, + /*Spaces=*/0, Tok.OriginalColumn, Tok.NewlinesBefore, "", "", + Tok.Tok.getKind(), InPPDirective && !Tok.IsFirst, + Tok.is(TT_StartOfName) || Tok.is(TT_FunctionDeclarationName), + /*IsInsideToken=*/false)); } void WhitespaceManager::replaceWhitespaceInToken( @@ -81,15 +84,10 @@ void WhitespaceManager::replaceWhitespaceInToken( Changes.push_back(Change( true, SourceRange(Start, Start.getLocWithOffset(ReplaceChars)), IndentLevel, Spaces, std::max(0, Spaces), Newlines, PreviousPostfix, - CurrentPrefix, - // If we don't add a newline this change doesn't start a comment. Thus, - // when we align line comments, we don't need to treat this change as one. - // FIXME: We still need to take this change in account to properly - // calculate the new length of the comment and to calculate the changes - // for which to do the alignment when aligning comments. - Tok.is(TT_LineComment) && Newlines > 0 ? tok::comment : tok::unknown, + CurrentPrefix, Tok.is(TT_LineComment) ? tok::comment : tok::unknown, InPPDirective && !Tok.IsFirst, - Tok.is(TT_StartOfName) || Tok.is(TT_FunctionDeclarationName))); + Tok.is(TT_StartOfName) || Tok.is(TT_FunctionDeclarationName), + /*IsInsideToken=*/Newlines == 0)); } const tooling::Replacements &WhitespaceManager::generateReplacements() { @@ -109,6 +107,7 @@ const tooling::Replacements &WhitespaceManager::generateReplacements() { void WhitespaceManager::calculateLineBreakInformation() { Changes[0].PreviousEndOfTokenColumn = 0; + Change *LastOutsideTokenChange = &Changes[0]; for (unsigned i = 1, e = Changes.size(); i != e; ++i) { unsigned OriginalWhitespaceStart = SourceMgr.getFileOffset(Changes[i].OriginalWhitespaceRange.getBegin()); @@ -119,11 +118,20 @@ void WhitespaceManager::calculateLineBreakInformation() { Changes[i].PreviousLinePostfix.size() + Changes[i - 1].CurrentLinePrefix.size(); + // If there are multiple changes in this token, sum up all the changes until + // the end of the line. + if (Changes[i - 1].IsInsideToken) + LastOutsideTokenChange->TokenLength += + Changes[i - 1].TokenLength + Changes[i - 1].Spaces; + else + LastOutsideTokenChange = &Changes[i - 1]; + Changes[i].PreviousEndOfTokenColumn = Changes[i - 1].StartOfTokenColumn + Changes[i - 1].TokenLength; Changes[i - 1].IsTrailingComment = - (Changes[i].NewlinesBefore > 0 || Changes[i].Kind == tok::eof) && + (Changes[i].NewlinesBefore > 0 || Changes[i].Kind == tok::eof || + (Changes[i].IsInsideToken && Changes[i].Kind == tok::comment)) && Changes[i - 1].Kind == tok::comment; } // FIXME: The last token is currently not always an eof token; in those @@ -133,6 +141,10 @@ void WhitespaceManager::calculateLineBreakInformation() { const WhitespaceManager::Change *LastBlockComment = nullptr; for (auto &Change : Changes) { + // Reset the IsTrailingComment flag for changes inside of trailing comments + // so they don't get realigned later. + if (Change.IsInsideToken) + Change.IsTrailingComment = false; Change.StartOfBlockComment = nullptr; Change.IndentationOffset = 0; if (Change.Kind == tok::comment) { @@ -342,6 +354,12 @@ void WhitespaceManager::alignTrailingComments() { unsigned ChangeMinColumn = Changes[i].StartOfTokenColumn; unsigned ChangeMaxColumn = Style.ColumnLimit - Changes[i].TokenLength; + + // If we don't create a replacement for this change, we have to consider + // it to be immovable. + if (!Changes[i].CreateReplacement) + ChangeMaxColumn = ChangeMinColumn; + if (i + 1 != e && Changes[i + 1].ContinuesPPDirective) ChangeMaxColumn -= 2; // If this comment follows an } in column 0, it probably documents the diff --git a/lib/Format/WhitespaceManager.h b/lib/Format/WhitespaceManager.h index f83971b4add6..9ca9db6f7488 100644 --- a/lib/Format/WhitespaceManager.h +++ b/lib/Format/WhitespaceManager.h @@ -109,7 +109,8 @@ public: unsigned IndentLevel, int Spaces, unsigned StartOfTokenColumn, unsigned NewlinesBefore, StringRef PreviousLinePostfix, StringRef CurrentLinePrefix, tok::TokenKind Kind, - bool ContinuesPPDirective, bool IsStartOfDeclName); + bool ContinuesPPDirective, bool IsStartOfDeclName, + bool IsInsideToken); bool CreateReplacement; // Changes might be in the middle of a token, so we cannot just keep the @@ -139,6 +140,10 @@ public: // comments. Uncompensated negative offset is truncated to 0. int Spaces; + // If this change is inside of a token but not at the start of the token or + // directly after a newline. + bool IsInsideToken; + // \c IsTrailingComment, \c TokenLength, \c PreviousEndOfTokenColumn and // \c EscapedNewlineColumn will be calculated in // \c calculateLineBreakInformation. diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 3a32f476566c..237a44704096 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -1,4 +1,4 @@ -//===--- +//===--- CompilerInvocation.cpp -------------------------------------------===// // // The LLVM Compiler Infrastructure // @@ -2202,8 +2202,11 @@ std::string CompilerInvocation::getModuleHash() const { code = hash_combine(code, I->first, I->second); } - // Extend the signature with the sysroot. - code = hash_combine(code, hsOpts.Sysroot, hsOpts.UseBuiltinIncludes, + // Extend the signature with the sysroot and other header search options. + code = hash_combine(code, hsOpts.Sysroot, + hsOpts.ModuleFormat, + hsOpts.UseDebugInfo, + hsOpts.UseBuiltinIncludes, hsOpts.UseStandardSystemIncludes, hsOpts.UseStandardCXXIncludes, hsOpts.UseLibcxx); diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp index d6c88d20fc2a..407ccea2e7d1 100644 --- a/lib/Frontend/FrontendActions.cpp +++ b/lib/Frontend/FrontendActions.cpp @@ -187,15 +187,17 @@ collectModuleHeaderIncludes(const LangOptions &LangOpts, FileManager &FileMgr, return std::error_code(); // Add includes for each of these headers. - for (Module::Header &H : Module->Headers[Module::HK_Normal]) { - Module->addTopHeader(H.Entry); - // Use the path as specified in the module map file. We'll look for this - // file relative to the module build directory (the directory containing - // the module map file) so this will find the same file that we found - // while parsing the module map. - if (std::error_code Err = addHeaderInclude(H.NameAsWritten, Includes, - LangOpts, Module->IsExternC)) - return Err; + for (auto HK : {Module::HK_Normal, Module::HK_Private}) { + for (Module::Header &H : Module->Headers[HK]) { + Module->addTopHeader(H.Entry); + // Use the path as specified in the module map file. We'll look for this + // file relative to the module build directory (the directory containing + // the module map file) so this will find the same file that we found + // while parsing the module map. + if (std::error_code Err = addHeaderInclude(H.NameAsWritten, Includes, + LangOpts, Module->IsExternC)) + return Err; + } } // Note that Module->PrivateHeaders will not be a TopHeader. diff --git a/lib/Frontend/MultiplexConsumer.cpp b/lib/Frontend/MultiplexConsumer.cpp index 12c85240bd75..f8b73e9034b3 100644 --- a/lib/Frontend/MultiplexConsumer.cpp +++ b/lib/Frontend/MultiplexConsumer.cpp @@ -119,6 +119,7 @@ public: const FunctionDecl *Delete) override; void CompletedImplicitDefinition(const FunctionDecl *D) override; void StaticDataMemberInstantiated(const VarDecl *D) override; + void DefaultArgumentInstantiated(const ParmVarDecl *D) override; void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD, const ObjCInterfaceDecl *IFD) override; void FunctionDefinitionInstantiated(const FunctionDecl *D) override; @@ -193,6 +194,11 @@ void MultiplexASTMutationListener::StaticDataMemberInstantiated( for (size_t i = 0, e = Listeners.size(); i != e; ++i) Listeners[i]->StaticDataMemberInstantiated(D); } +void MultiplexASTMutationListener::DefaultArgumentInstantiated( + const ParmVarDecl *D) { + for (size_t i = 0, e = Listeners.size(); i != e; ++i) + Listeners[i]->DefaultArgumentInstantiated(D); +} void MultiplexASTMutationListener::AddedObjCCategoryToInterface( const ObjCCategoryDecl *CatD, const ObjCInterfaceDecl *IFD) { diff --git a/lib/Headers/altivec.h b/lib/Headers/altivec.h index dc0dcbc7385c..a5b4f7434d1c 100644 --- a/lib/Headers/altivec.h +++ b/lib/Headers/altivec.h @@ -1891,6 +1891,22 @@ static vector float __ATTRS_o_ai vec_ctf(vector unsigned int __a, int __b) { return __builtin_altivec_vcfux((vector int)__a, __b); } +#ifdef __VSX__ +static vector double __ATTRS_o_ai vec_ctf(vector unsigned long long __a, + int __b) { + vector double __ret = __builtin_convertvector(__a, vector double); + __ret *= (vector double)(vector unsigned long long)((0x3ffULL - __b) << 52); + return __ret; +} + +static vector double __ATTRS_o_ai vec_ctf(vector signed long long __a, + int __b) { + vector double __ret = __builtin_convertvector(__a, vector double); + __ret *= (vector double)(vector unsigned long long)((0x3ffULL - __b) << 52); + return __ret; +} +#endif + /* vec_vcfsx */ static vector float __attribute__((__always_inline__)) @@ -1907,11 +1923,18 @@ vec_vcfux(vector unsigned int __a, int __b) { /* vec_cts */ -static vector int __attribute__((__always_inline__)) -vec_cts(vector float __a, int __b) { +static vector int __ATTRS_o_ai vec_cts(vector float __a, int __b) { return __builtin_altivec_vctsxs(__a, __b); } +#ifdef __VSX__ +static vector signed long long __ATTRS_o_ai vec_cts(vector double __a, + int __b) { + __a *= (vector double)(vector unsigned long long)((0x3ffULL + __b) << 52); + return __builtin_convertvector(__a, vector signed long long); +} +#endif + /* vec_vctsxs */ static vector int __attribute__((__always_inline__)) @@ -1921,11 +1944,18 @@ vec_vctsxs(vector float __a, int __b) { /* vec_ctu */ -static vector unsigned int __attribute__((__always_inline__)) -vec_ctu(vector float __a, int __b) { +static vector unsigned int __ATTRS_o_ai vec_ctu(vector float __a, int __b) { return __builtin_altivec_vctuxs(__a, __b); } +#ifdef __VSX__ +static vector unsigned long long __ATTRS_o_ai vec_ctu(vector double __a, + int __b) { + __a *= (vector double)(vector unsigned long long)((0x3ffULL + __b) << 52); + return __builtin_convertvector(__a, vector unsigned long long); +} +#endif + /* vec_vctuxs */ static vector unsigned int __attribute__((__always_inline__)) diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp index 8a686a7f3d74..2d005dd2e1f0 100644 --- a/lib/Lex/HeaderSearch.cpp +++ b/lib/Lex/HeaderSearch.cpp @@ -153,8 +153,7 @@ std::string HeaderSearch::getModuleFileName(StringRef ModuleName, auto FileName = llvm::sys::path::filename(ModuleMapPath); llvm::hash_code Hash = - llvm::hash_combine(DirName.lower(), FileName.lower(), - HSOpts->ModuleFormat, HSOpts->UseDebugInfo); + llvm::hash_combine(DirName.lower(), FileName.lower()); SmallString<128> HashStr; llvm::APInt(64, size_t(Hash)).toStringUnsigned(HashStr, /*Radix*/36); diff --git a/lib/Lex/LiteralSupport.cpp b/lib/Lex/LiteralSupport.cpp index 1e7858af8948..5b1c49344e8d 100644 --- a/lib/Lex/LiteralSupport.cpp +++ b/lib/Lex/LiteralSupport.cpp @@ -983,6 +983,7 @@ NumericLiteralParser::GetFloatValue(llvm::APFloat &Result) { /// u' c-char-sequence ' /// U' c-char-sequence ' /// L' c-char-sequence ' +/// u8' c-char-sequence ' [C++1z lex.ccon] /// c-char-sequence: /// c-char /// c-char-sequence c-char diff --git a/lib/Lex/Pragma.cpp b/lib/Lex/Pragma.cpp index 3134790ccb90..afb41a240776 100644 --- a/lib/Lex/Pragma.cpp +++ b/lib/Lex/Pragma.cpp @@ -876,6 +876,22 @@ struct PragmaDebugHandler : public PragmaHandler { Crasher.setKind(tok::annot_pragma_parser_crash); Crasher.setAnnotationRange(SourceRange(Tok.getLocation())); PP.EnterToken(Crasher); + } else if (II->isStr("dump")) { + Token Identifier; + PP.LexUnexpandedToken(Identifier); + if (auto *DumpII = Identifier.getIdentifierInfo()) { + Token DumpAnnot; + DumpAnnot.startToken(); + DumpAnnot.setKind(tok::annot_pragma_dump); + DumpAnnot.setAnnotationRange( + SourceRange(Tok.getLocation(), Identifier.getLocation())); + DumpAnnot.setAnnotationValue(DumpII); + PP.DiscardUntilEndOfDirective(); + PP.EnterToken(DumpAnnot); + } else { + PP.Diag(Identifier, diag::warn_pragma_debug_missing_argument) + << II->getName(); + } } else if (II->isStr("llvm_fatal_error")) { llvm::report_fatal_error("#pragma clang __debug llvm_fatal_error"); } else if (II->isStr("llvm_unreachable")) { @@ -887,7 +903,8 @@ struct PragmaDebugHandler : public PragmaHandler { if (MacroII) PP.dumpMacroInfo(MacroII); else - PP.Diag(MacroName, diag::warn_pragma_diagnostic_invalid); + PP.Diag(MacroName, diag::warn_pragma_debug_missing_argument) + << II->getName(); } else if (II->isStr("overflow_stack")) { DebugOverflowStack(); } else if (II->isStr("handle_crash")) { diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index e69bb2745c43..c64b97d01b9a 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -3326,6 +3326,15 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, case tok::kw___bool: isInvalid = DS.SetTypeAltiVecBool(true, Loc, PrevSpec, DiagID, Policy); break; + case tok::kw_pipe: + if (!getLangOpts().OpenCL || (getLangOpts().OpenCLVersion < 200)) { + // OpenCL 2.0 defined this keyword. OpenCL 1.2 and earlier should + // support the "pipe" word as identifier. + Tok.getIdentifierInfo()->revertTokenIDToIdentifier(); + goto DoneWithDeclSpec; + } + isInvalid = DS.SetTypePipe(true, Loc, PrevSpec, DiagID, Policy); + break; case tok::kw___unknown_anytype: isInvalid = DS.SetTypeSpecType(TST_unknown_anytype, Loc, PrevSpec, DiagID, Policy); @@ -4401,6 +4410,9 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { switch (Tok.getKind()) { default: return false; + case tok::kw_pipe: + return getLangOpts().OpenCL && (getLangOpts().OpenCLVersion >= 200); + case tok::identifier: // foo::bar // Unfortunate hack to support "Class.factoryMethod" notation. if (getLangOpts().ObjC1 && NextToken().is(tok::period)) @@ -4847,6 +4859,9 @@ static bool isPtrOperatorToken(tok::TokenKind Kind, const LangOptions &Lang, if (Kind == tok::star || Kind == tok::caret) return true; + if ((Kind == tok::kw_pipe) && Lang.OpenCL && (Lang.OpenCLVersion >= 200)) + return true; + if (!Lang.CPlusPlus) return false; @@ -4865,6 +4880,17 @@ static bool isPtrOperatorToken(tok::TokenKind Kind, const LangOptions &Lang, return false; } +// Indicates whether the given declarator is a pipe declarator. +static bool isPipeDeclerator(const Declarator &D) { + const unsigned NumTypes = D.getNumTypeObjects(); + + for (unsigned Idx = 0; Idx != NumTypes; ++Idx) + if (DeclaratorChunk::Pipe == D.getTypeObject(Idx).Kind) + return true; + + return false; +} + /// ParseDeclaratorInternal - Parse a C or C++ declarator. The direct-declarator /// is parsed by the function passed to it. Pass null, and the direct-declarator /// isn't parsed at all, making this function effectively parse the C++ @@ -4941,6 +4967,15 @@ void Parser::ParseDeclaratorInternal(Declarator &D, } tok::TokenKind Kind = Tok.getKind(); + + if (D.getDeclSpec().isTypeSpecPipe() && !isPipeDeclerator(D)) { + DeclSpec &DS = D.getMutableDeclSpec(); + + D.AddTypeInfo( + DeclaratorChunk::getPipe(DS.getTypeQualifiers(), DS.getPipeLoc()), + DS.getAttributes(), SourceLocation()); + } + // Not a pointer, C++ reference, or block. if (!isPtrOperatorToken(Kind, getLangOpts(), D.getContext())) { if (DirectDeclParser) @@ -6092,6 +6127,7 @@ void Parser::ParseMisplacedBracketDeclarator(Declarator &D) { case DeclaratorChunk::Reference: case DeclaratorChunk::BlockPointer: case DeclaratorChunk::MemberPointer: + case DeclaratorChunk::Pipe: NeedParens = true; break; case DeclaratorChunk::Array: diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index a4de9751f9a0..3f22ad4ddaba 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -3363,7 +3363,8 @@ Parser::tryParseExceptionSpecification(bool Delayed, ConsumeAndStoreUntil(tok::r_paren, *ExceptionSpecTokens, /*StopAtSemi=*/true, /*ConsumeFinalToken=*/true); - SpecificationRange.setEnd(Tok.getLocation()); + SpecificationRange.setEnd(ExceptionSpecTokens->back().getLocation()); + return EST_Unparsed; } diff --git a/lib/Parse/ParseOpenMP.cpp b/lib/Parse/ParseOpenMP.cpp index 078f4c388705..a08db5490fa9 100644 --- a/lib/Parse/ParseOpenMP.cpp +++ b/lib/Parse/ParseOpenMP.cpp @@ -165,8 +165,8 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() { /// 'distribute' /// annot_pragma_openmp_end /// -StmtResult -Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) { +StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective( + AllowedContsructsKind Allowed) { assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!"); ParenBraceBracketBalancer BalancerRAIIObj(*this); SmallVector Identifiers; @@ -186,6 +186,10 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) { switch (DKind) { case OMPD_threadprivate: + if (Allowed != ACK_Any) { + Diag(Tok, diag::err_omp_immediate_directive) + << getOpenMPDirectiveName(DKind) << 0; + } ConsumeToken(); if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, false)) { // The last seen token is annot_pragma_openmp_end - need to check for @@ -213,7 +217,7 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) { case OMPD_taskwait: case OMPD_cancellation_point: case OMPD_cancel: - if (!StandAloneAllowed) { + if (Allowed == ACK_StatementsOpenMPNonStandalone) { Diag(Tok, diag::err_omp_immediate_directive) << getOpenMPDirectiveName(DKind) << 0; } @@ -299,7 +303,7 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) { // If the depend clause is specified, the ordered construct is a stand-alone // directive. if (DKind == OMPD_ordered && FirstClauses[OMPC_depend].getInt()) { - if (!StandAloneAllowed) { + if (Allowed == ACK_StatementsOpenMPNonStandalone) { Diag(Loc, diag::err_omp_immediate_directive) << getOpenMPDirectiveName(DKind) << 1 << getOpenMPClauseName(OMPC_depend); diff --git a/lib/Parse/ParsePragma.cpp b/lib/Parse/ParsePragma.cpp index 4430eb8d03da..bc70942851e2 100644 --- a/lib/Parse/ParsePragma.cpp +++ b/lib/Parse/ParsePragma.cpp @@ -377,6 +377,14 @@ void Parser::HandlePragmaAlign() { Actions.ActOnPragmaOptionsAlign(Kind, PragmaLoc); } +void Parser::HandlePragmaDump() { + assert(Tok.is(tok::annot_pragma_dump)); + IdentifierInfo *II = + reinterpret_cast(Tok.getAnnotationValue()); + Actions.ActOnPragmaDump(getCurScope(), Tok.getLocation(), II); + ConsumeToken(); +} + void Parser::HandlePragmaWeak() { assert(Tok.is(tok::annot_pragma_weak)); SourceLocation PragmaLoc = ConsumeToken(); diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index 717bcff0c168..edf0dda7df8c 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -32,14 +32,18 @@ using namespace clang; /// \brief Parse a standalone statement (for instance, as the body of an 'if', /// 'while', or 'for'). -StmtResult Parser::ParseStatement(SourceLocation *TrailingElseLoc) { +StmtResult Parser::ParseStatement(SourceLocation *TrailingElseLoc, + bool AllowOpenMPStandalone) { StmtResult Res; // We may get back a null statement if we found a #pragma. Keep going until // we get an actual statement. do { StmtVector Stmts; - Res = ParseStatementOrDeclaration(Stmts, true, TrailingElseLoc); + Res = ParseStatementOrDeclaration( + Stmts, AllowOpenMPStandalone ? ACK_StatementsOpenMPAnyExecutable + : ACK_StatementsOpenMPNonStandalone, + TrailingElseLoc); } while (!Res.isInvalid() && !Res.get()); return Res; @@ -95,7 +99,8 @@ StmtResult Parser::ParseStatement(SourceLocation *TrailingElseLoc) { /// [OBC] '@' 'throw' ';' /// StmtResult -Parser::ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement, +Parser::ParseStatementOrDeclaration(StmtVector &Stmts, + AllowedContsructsKind Allowed, SourceLocation *TrailingElseLoc) { ParenBraceBracketBalancer BalancerRAIIObj(*this); @@ -103,8 +108,8 @@ Parser::ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement, ParsedAttributesWithRange Attrs(AttrFactory); MaybeParseCXX11Attributes(Attrs, nullptr, /*MightBeObjCMessageSend*/ true); - StmtResult Res = ParseStatementOrDeclarationAfterAttributes(Stmts, - OnlyStatement, TrailingElseLoc, Attrs); + StmtResult Res = ParseStatementOrDeclarationAfterAttributes( + Stmts, Allowed, TrailingElseLoc, Attrs); assert((Attrs.empty() || Res.isInvalid() || Res.isUsable()) && "attributes on empty statement"); @@ -146,7 +151,7 @@ private: StmtResult Parser::ParseStatementOrDeclarationAfterAttributes(StmtVector &Stmts, - bool OnlyStatement, SourceLocation *TrailingElseLoc, + AllowedContsructsKind Allowed, SourceLocation *TrailingElseLoc, ParsedAttributesWithRange &Attrs) { const char *SemiError = nullptr; StmtResult Res; @@ -202,7 +207,8 @@ Retry: } default: { - if ((getLangOpts().CPlusPlus || !OnlyStatement) && isDeclarationStatement()) { + if ((getLangOpts().CPlusPlus || Allowed == ACK_Any) && + isDeclarationStatement()) { SourceLocation DeclStart = Tok.getLocation(), DeclEnd; DeclGroupPtrTy Decl = ParseDeclaration(Declarator::BlockContext, DeclEnd, Attrs); @@ -346,7 +352,7 @@ Retry: case tok::annot_pragma_openmp: ProhibitAttributes(Attrs); - return ParseOpenMPDeclarativeOrExecutableDirective(!OnlyStatement); + return ParseOpenMPDeclarativeOrExecutableDirective(Allowed); case tok::annot_pragma_ms_pointers_to_members: ProhibitAttributes(Attrs); @@ -365,7 +371,11 @@ Retry: case tok::annot_pragma_loop_hint: ProhibitAttributes(Attrs); - return ParsePragmaLoopHint(Stmts, OnlyStatement, TrailingElseLoc, Attrs); + return ParsePragmaLoopHint(Stmts, Allowed, TrailingElseLoc, Attrs); + + case tok::annot_pragma_dump: + HandlePragmaDump(); + return StmtEmpty(); } // If we reached this code, the statement must end in a semicolon. @@ -583,7 +593,8 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributesWithRange &attrs) { // can't handle GNU attributes), so only call it in the one case where // GNU attributes are allowed. SubStmt = ParseStatementOrDeclarationAfterAttributes( - Stmts, /*OnlyStmts*/ true, nullptr, TempAttrs); + Stmts, /*Allowed=*/ACK_StatementsOpenMPNonStandalone, nullptr, + TempAttrs); if (!TempAttrs.empty() && !SubStmt.isInvalid()) SubStmt = Actions.ProcessStmtAttributes( SubStmt.get(), TempAttrs.getList(), TempAttrs.Range); @@ -722,7 +733,8 @@ StmtResult Parser::ParseCaseStatement(bool MissingCase, ExprResult Expr) { // continue parsing the sub-stmt. if (Case.isInvalid()) { if (TopLevelCase.isInvalid()) // No parsed case stmts. - return ParseStatement(); + return ParseStatement(/*TrailingElseLoc=*/nullptr, + /*AllowOpenMPStandalone=*/true); // Otherwise, just don't add it as a nested case. } else { // If this is the first case statement we parsed, it becomes TopLevelCase. @@ -742,7 +754,8 @@ StmtResult Parser::ParseCaseStatement(bool MissingCase, ExprResult Expr) { StmtResult SubStmt; if (Tok.isNot(tok::r_brace)) { - SubStmt = ParseStatement(); + SubStmt = ParseStatement(/*TrailingElseLoc=*/nullptr, + /*AllowOpenMPStandalone=*/true); } else { // Nicely diagnose the common error "switch (X) { case 4: }", which is // not valid. If ColonLoc doesn't point to a valid text location, there was @@ -794,7 +807,8 @@ StmtResult Parser::ParseDefaultStatement() { StmtResult SubStmt; if (Tok.isNot(tok::r_brace)) { - SubStmt = ParseStatement(); + SubStmt = ParseStatement(/*TrailingElseLoc=*/nullptr, + /*AllowOpenMPStandalone=*/true); } else { // Diagnose the common error "switch (X) {... default: }", which is // not valid. @@ -893,6 +907,9 @@ void Parser::ParseCompoundStatementLeadingPragmas() { case tok::annot_pragma_ms_vtordisp: HandlePragmaMSVtorDisp(); break; + case tok::annot_pragma_dump: + HandlePragmaDump(); + break; default: checkForPragmas = false; break; @@ -965,7 +982,7 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { StmtResult R; if (Tok.isNot(tok::kw___extension__)) { - R = ParseStatementOrDeclaration(Stmts, false); + R = ParseStatementOrDeclaration(Stmts, ACK_Any); } else { // __extension__ can start declarations and it can also be a unary // operator for expressions. Consume multiple __extension__ markers here @@ -1861,7 +1878,8 @@ StmtResult Parser::ParseReturnStatement() { return Actions.ActOnReturnStmt(ReturnLoc, R.get(), getCurScope()); } -StmtResult Parser::ParsePragmaLoopHint(StmtVector &Stmts, bool OnlyStatement, +StmtResult Parser::ParsePragmaLoopHint(StmtVector &Stmts, + AllowedContsructsKind Allowed, SourceLocation *TrailingElseLoc, ParsedAttributesWithRange &Attrs) { // Create temporary attribute list. @@ -1884,7 +1902,7 @@ StmtResult Parser::ParsePragmaLoopHint(StmtVector &Stmts, bool OnlyStatement, MaybeParseCXX11Attributes(Attrs); StmtResult S = ParseStatementOrDeclarationAfterAttributes( - Stmts, OnlyStatement, TrailingElseLoc, Attrs); + Stmts, Allowed, TrailingElseLoc, Attrs); Attrs.takeAllFrom(TempAttrs); return S; @@ -2182,7 +2200,7 @@ void Parser::ParseMicrosoftIfExistsStatement(StmtVector &Stmts) { // Condition is true, parse the statements. while (Tok.isNot(tok::r_brace)) { - StmtResult R = ParseStatementOrDeclaration(Stmts, false); + StmtResult R = ParseStatementOrDeclaration(Stmts, ACK_Any); if (R.isUsable()) Stmts.push_back(R.get()); } diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index b3eeb9d58ff4..ccefb3dd3f5d 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -668,6 +668,9 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, case tok::annot_pragma_ms_pragma: HandlePragmaMSPragma(); return DeclGroupPtrTy(); + case tok::annot_pragma_dump: + HandlePragmaDump(); + return DeclGroupPtrTy(); case tok::semi: // Either a C++11 empty-declaration or attribute-declaration. SingleDecl = Actions.ActOnEmptyDeclaration(getCurScope(), diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp index d664d8704003..6f6c4ca5848f 100644 --- a/lib/Sema/DeclSpec.cpp +++ b/lib/Sema/DeclSpec.cpp @@ -270,6 +270,7 @@ bool Declarator::isDeclarationOfFunction() const { case DeclaratorChunk::Array: case DeclaratorChunk::BlockPointer: case DeclaratorChunk::MemberPointer: + case DeclaratorChunk::Pipe: return false; } llvm_unreachable("Invalid type chunk"); @@ -713,6 +714,22 @@ bool DeclSpec::SetTypeAltiVecVector(bool isAltiVecVector, SourceLocation Loc, return false; } +bool DeclSpec::SetTypePipe(bool isPipe, SourceLocation Loc, + const char *&PrevSpec, unsigned &DiagID, + const PrintingPolicy &Policy) { + + if (TypeSpecType != TST_unspecified) { + PrevSpec = DeclSpec::getSpecifierName((TST)TypeSpecType, Policy); + DiagID = diag::err_invalid_decl_spec_combination; + return true; + } + + if (isPipe) { + TypeSpecPipe = TSP_pipe; + } + return false; +} + bool DeclSpec::SetTypeAltiVecPixel(bool isAltiVecPixel, SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID, const PrintingPolicy &Policy) { diff --git a/lib/Sema/SemaCast.cpp b/lib/Sema/SemaCast.cpp index 07b058911c2d..ad1d7da4d070 100644 --- a/lib/Sema/SemaCast.cpp +++ b/lib/Sema/SemaCast.cpp @@ -2105,6 +2105,7 @@ void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle, && (SrcExpr.get()->getType()->isIntegerType() || SrcExpr.get()->getType()->isFloatingType())) { Kind = CK_VectorSplat; + SrcExpr = Self.prepareVectorSplat(DestType, SrcExpr.get()); return; } @@ -2339,6 +2340,7 @@ void CastOperation::CheckCStyleCast() { if (DestVecTy->getVectorKind() == VectorType::AltiVecVector && (SrcType->isIntegerType() || SrcType->isFloatingType())) { Kind = CK_VectorSplat; + SrcExpr = Self.prepareVectorSplat(DestType, SrcExpr.get()); } else if (Self.CheckVectorCast(OpRange, DestType, SrcType, Kind)) { SrcExpr = ExprError(); } diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index cbdcb5e48391..6c2834b750ae 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -6243,7 +6243,8 @@ static IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) { IntRange OutputTypeRange = IntRange::forValueOfType(C, GetExprType(CE)); - bool isIntegerCast = (CE->getCastKind() == CK_IntegralCast); + bool isIntegerCast = CE->getCastKind() == CK_IntegralCast || + CE->getCastKind() == CK_BooleanToSignedIntegral; // Assume that non-integer casts can span the full range of the type. if (!isIntegerCast) @@ -7047,6 +7048,10 @@ static void DiagnoseNullConversion(Sema &S, Expr *E, QualType T, E->getExprLoc())) return; + // Don't warn on functions which have return type nullptr_t. + if (isa(E)) + return; + // Check for NULL (GNUNull) or nullptr (CXX11_nullptr). const Expr::NullPointerConstantKind NullKind = E->isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNotNull); @@ -7062,8 +7067,12 @@ static void DiagnoseNullConversion(Sema &S, Expr *E, QualType T, // __null is usually wrapped in a macro. Go up a macro if that is the case. if (NullKind == Expr::NPCK_GNUNull) { - if (Loc.isMacroID()) - Loc = S.SourceMgr.getImmediateExpansionRange(Loc).first; + if (Loc.isMacroID()) { + StringRef MacroName = + Lexer::getImmediateMacroName(Loc, S.SourceMgr, S.getLangOpts()); + if (MacroName == "NULL") + Loc = S.SourceMgr.getImmediateExpansionRange(Loc).first; + } } // Only warn if the null and context location are in the same macro expansion. @@ -7845,6 +7854,10 @@ void Sema::CheckBoolLikeConversion(Expr *E, SourceLocation CC) { void Sema::CheckForIntOverflow (Expr *E) { if (isa(E->IgnoreParenCasts())) E->IgnoreParenCasts()->EvaluateForOverflow(Context); + else if (auto InitList = dyn_cast(E)) + for (Expr *E : InitList->inits()) + if (isa(E->IgnoreParenCasts())) + E->IgnoreParenCasts()->EvaluateForOverflow(Context); } namespace { diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index f27fb2b10712..f95d1068cc59 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -3962,9 +3962,6 @@ static bool CheckAnonMemberRedeclaration(Sema &SemaRef, Sema::ForRedeclaration); if (!SemaRef.LookupName(R, S)) return false; - if (R.getAsSingle()) - return false; - // Pick a representative declaration. NamedDecl *PrevDecl = R.getRepresentativeDecl()->getUnderlyingDecl(); assert(PrevDecl && "Expected a non-null Decl"); @@ -4675,11 +4672,13 @@ bool Sema::DiagnoseClassNameShadow(DeclContext *DC, DeclarationNameInfo NameInfo) { DeclarationName Name = NameInfo.getName(); - if (CXXRecordDecl *Record = dyn_cast(DC)) - if (Record->getIdentifier() && Record->getDeclName() == Name) { - Diag(NameInfo.getLoc(), diag::err_member_name_of_class) << Name; - return true; - } + CXXRecordDecl *Record = dyn_cast(DC); + while (Record && Record->isAnonymousStructOrUnion()) + Record = dyn_cast(Record->getParent()); + if (Record && Record->getIdentifier() && Record->getDeclName() == Name) { + Diag(NameInfo.getLoc(), diag::err_member_name_of_class) << Name; + return true; + } return false; } @@ -8257,6 +8256,23 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, for (auto Param : NewFD->params()) checkIsValidOpenCLKernelParameter(*this, D, Param, ValidTypes); } + for (FunctionDecl::param_iterator PI = NewFD->param_begin(), + PE = NewFD->param_end(); PI != PE; ++PI) { + ParmVarDecl *Param = *PI; + QualType PT = Param->getType(); + + // OpenCL 2.0 pipe restrictions forbids pipe packet types to be non-value + // types. + if (getLangOpts().OpenCLVersion >= 200) { + if(const PipeType *PipeTy = PT->getAs()) { + QualType ElemTy = PipeTy->getElementType(); + if (ElemTy->isReferenceType() || ElemTy->isPointerType()) { + Diag(Param->getTypeSpecStartLoc(), diag::err_reference_pipe_type ); + D.setInvalidType(); + } + } + } + } MarkUnusedFileScopedDecl(NewFD); @@ -11799,6 +11815,28 @@ static bool isAcceptableTagRedeclContext(Sema &S, DeclContext *OldDC, return false; } +/// Find the DeclContext in which a tag is implicitly declared if we see an +/// elaborated type specifier in the specified context, and lookup finds +/// nothing. +static DeclContext *getTagInjectionContext(DeclContext *DC) { + while (!DC->isFileContext() && !DC->isFunctionOrMethod()) + DC = DC->getParent(); + return DC; +} + +/// Find the Scope in which a tag is implicitly declared if we see an +/// elaborated type specifier in the specified context, and lookup finds +/// nothing. +static Scope *getTagInjectionScope(Scope *S, const LangOptions &LangOpts) { + while (S->isClassScope() || + (LangOpts.CPlusPlus && + S->isFunctionPrototypeScope()) || + ((S->getFlags() & Scope::DeclScope) == 0) || + (S->getEntity() && S->getEntity()->isTransparentContext())) + S = S->getParent(); + return S; +} + /// \brief This is invoked when we see 'struct foo' or 'struct {'. In the /// former case, Name will be non-null. In the later case, Name will be null. /// TagSpec indicates what kind of tag this is. TUK indicates whether this is a @@ -12115,16 +12153,10 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // Find the context where we'll be declaring the tag. // FIXME: We would like to maintain the current DeclContext as the // lexical context, - while (!SearchDC->isFileContext() && !SearchDC->isFunctionOrMethod()) - SearchDC = SearchDC->getParent(); + SearchDC = getTagInjectionContext(SearchDC); // Find the scope where we'll be declaring the tag. - while (S->isClassScope() || - (getLangOpts().CPlusPlus && - S->isFunctionPrototypeScope()) || - ((S->getFlags() & Scope::DeclScope) == 0) || - (S->getEntity() && S->getEntity()->isTransparentContext())) - S = S->getParent(); + S = getTagInjectionScope(S, getLangOpts()); } else { assert(TUK == TUK_Friend); // C++ [namespace.memdef]p3: @@ -12284,7 +12316,8 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, } else if (TUK == TUK_Reference && (PrevTagDecl->getFriendObjectKind() == Decl::FOK_Undeclared || - getOwningModule(PrevDecl) != + PP.getModuleContainingLocation( + PrevDecl->getLocation()) != PP.getModuleContainingLocation(KWLoc)) && SS.isEmpty()) { // This declaration is a reference to an existing entity, but @@ -12294,14 +12327,12 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // the declaration would have meant the same thing if no prior // declaration were found, that is, if it was found in the same // scope where we would have injected a declaration. - DeclContext *InjectedDC = CurContext; - while (!InjectedDC->isFileContext() && - !InjectedDC->isFunctionOrMethod()) - InjectedDC = InjectedDC->getParent(); - if (!InjectedDC->getRedeclContext()->Equals( - PrevDecl->getDeclContext()->getRedeclContext())) + if (!getTagInjectionContext(CurContext)->getRedeclContext() + ->Equals(PrevDecl->getDeclContext()->getRedeclContext())) return PrevTagDecl; - // This is in the injected scope, create a new declaration. + // This is in the injected scope, create a new declaration in + // that scope. + S = getTagInjectionScope(S, getLangOpts()); } else { return PrevTagDecl; } @@ -12603,7 +12634,7 @@ CreateNewDecl: << Name; Invalid = true; } - } else { + } else if (!PrevDecl) { Diag(Loc, diag::warn_decl_in_param_list) << Context.getTagDeclType(New); } DeclsInPrototypeScope.push_back(New); diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 5a0f0f84af7e..f94c822b90f5 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -348,6 +348,25 @@ static void handleSimpleAttribute(Sema &S, Decl *D, Attr.getAttributeSpellingListIndex())); } +template +static void handleSimpleAttributeWithExclusions(Sema &S, Decl *D, + const AttributeList &Attr) { + handleSimpleAttribute(S, D, Attr); +} + +/// \brief Applies the given attribute to the Decl so long as the Decl doesn't +/// already have one of the given incompatible attributes. +template +static void handleSimpleAttributeWithExclusions(Sema &S, Decl *D, + const AttributeList &Attr) { + if (checkAttrMutualExclusion(S, D, Attr.getRange(), + Attr.getName())) + return; + handleSimpleAttributeWithExclusions(S, D, + Attr); +} + /// \brief Check if the passed-in expression is of type int or bool. static bool isIntOrBool(Expr *Exp) { QualType QT = Exp->getType(); @@ -3588,6 +3607,12 @@ static void handleOptimizeNoneAttr(Sema &S, Decl *D, } static void handleGlobalAttr(Sema &S, Decl *D, const AttributeList &Attr) { + if (checkAttrMutualExclusion(S, D, Attr.getRange(), + Attr.getName()) || + checkAttrMutualExclusion(S, D, Attr.getRange(), + Attr.getName())) { + return; + } FunctionDecl *FD = cast(D); if (!FD->getReturnType()->isVoidType()) { SourceRange RTRange = FD->getReturnTypeSourceRange(); @@ -4558,14 +4583,6 @@ static void handleInterruptAttr(Sema &S, Decl *D, const AttributeList &Attr) { handleARMInterruptAttr(S, D, Attr); } -static void handleMips16Attribute(Sema &S, Decl *D, const AttributeList &Attr) { - if (checkAttrMutualExclusion(S, D, Attr.getRange(), - Attr.getName())) - return; - - handleSimpleAttribute(S, D, Attr); -} - static void handleAMDGPUNumVGPRAttr(Sema &S, Decl *D, const AttributeList &Attr) { uint32_t NumRegs; @@ -4955,7 +4972,8 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, handleDLLAttr(S, D, Attr); break; case AttributeList::AT_Mips16: - handleMips16Attribute(S, D, Attr); + handleSimpleAttributeWithExclusions(S, D, + Attr); break; case AttributeList::AT_NoMips16: handleSimpleAttribute(S, D, Attr); @@ -5006,7 +5024,8 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, handleCommonAttr(S, D, Attr); break; case AttributeList::AT_CUDAConstant: - handleSimpleAttribute(S, D, Attr); + handleSimpleAttributeWithExclusions(S, D, + Attr); break; case AttributeList::AT_PassObjectSize: handlePassObjectSizeAttr(S, D, Attr); @@ -5051,10 +5070,12 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, handleGlobalAttr(S, D, Attr); break; case AttributeList::AT_CUDADevice: - handleSimpleAttribute(S, D, Attr); + handleSimpleAttributeWithExclusions(S, D, + Attr); break; case AttributeList::AT_CUDAHost: - handleSimpleAttribute(S, D, Attr); + handleSimpleAttributeWithExclusions(S, D, + Attr); break; case AttributeList::AT_GNUInline: handleGNUInlineAttr(S, D, Attr); @@ -5114,7 +5135,8 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, handleSimpleAttribute(S, D, Attr); break; case AttributeList::AT_CUDAShared: - handleSimpleAttribute(S, D, Attr); + handleSimpleAttributeWithExclusions(S, D, + Attr); break; case AttributeList::AT_VecReturn: handleVecReturnAttr(S, D, Attr); diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 02091a7bd530..11f232934e5a 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -7000,6 +7000,7 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R, case DeclaratorChunk::BlockPointer: case DeclaratorChunk::Reference: case DeclaratorChunk::MemberPointer: + case DeclaratorChunk::Pipe: extendLeft(Before, Chunk.getSourceRange()); break; @@ -7796,6 +7797,10 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, if (UsingShadowDecl *Shadow = dyn_cast(*I)) PrevShadow = Shadow; FoundEquivalentDecl = true; + } else if (isEquivalentInternalLinkageDeclaration(D, Target)) { + // We don't conflict with an existing using shadow decl of an equivalent + // declaration, but we're not a redeclaration of it. + FoundEquivalentDecl = true; } if (isVisible(D)) diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 5d0c6057f54f..3e89af625d1a 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -3084,6 +3084,8 @@ ExprResult Sema::ActOnCharacterConstant(const Token &Tok, Scope *UDLScope) { Kind = CharacterLiteral::UTF16; else if (Literal.isUTF32()) Kind = CharacterLiteral::UTF32; + else if (Literal.isUTF8()) + Kind = CharacterLiteral::UTF8; Expr *Lit = new (Context) CharacterLiteral(Literal.getValue(), Kind, Ty, Tok.getLocation()); @@ -4313,10 +4315,16 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc, if (Result.isInvalid()) return ExprError(); - Expr *Arg = Result.getAs(); - CheckCompletedExpr(Arg, Param->getOuterLocStart()); - // Build the default argument expression. - return CXXDefaultArgExpr::Create(Context, CallLoc, Param, Arg); + Result = ActOnFinishFullExpr(Result.getAs(), + Param->getOuterLocStart()); + if (Result.isInvalid()) + return ExprError(); + + // Remember the instantiated default argument. + Param->setDefaultArg(Result.getAs()); + if (ASTMutationListener *L = getASTMutationListener()) { + L->DefaultArgumentInstantiated(Param); + } } // If the default expression creates temporaries, we need to @@ -4929,7 +4937,9 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, OverloadExpr *ovl = find.Expression; if (UnresolvedLookupExpr *ULE = dyn_cast(ovl)) return BuildOverloadedCallExpr(S, Fn, ULE, LParenLoc, ArgExprs, - RParenLoc, ExecConfig); + RParenLoc, ExecConfig, + /*AllowTypoCorrection=*/true, + find.IsAddressOfOperand); return BuildCallToMemberFunction(S, Fn, LParenLoc, ArgExprs, RParenLoc); } } @@ -4943,10 +4953,14 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, Expr *NakedFn = Fn->IgnoreParens(); + bool CallingNDeclIndirectly = false; NamedDecl *NDecl = nullptr; - if (UnaryOperator *UnOp = dyn_cast(NakedFn)) - if (UnOp->getOpcode() == UO_AddrOf) + if (UnaryOperator *UnOp = dyn_cast(NakedFn)) { + if (UnOp->getOpcode() == UO_AddrOf) { + CallingNDeclIndirectly = true; NakedFn = UnOp->getSubExpr()->IgnoreParens(); + } + } if (isa(NakedFn)) { NDecl = cast(NakedFn)->getDecl(); @@ -4968,6 +4982,11 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, NDecl = cast(NakedFn)->getMemberDecl(); if (FunctionDecl *FD = dyn_cast_or_null(NDecl)) { + if (CallingNDeclIndirectly && + !checkAddressOfFunctionIsAvailable(FD, /*Complain=*/true, + Fn->getLocStart())) + return ExprError(); + if (FD->hasAttr()) { if (const EnableIfAttr *Attr = CheckEnableIf(FD, ArgExprs, true)) { Diag(Fn->getLocStart(), @@ -5583,6 +5602,39 @@ bool Sema::CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty, return false; } +ExprResult Sema::prepareVectorSplat(QualType VectorTy, Expr *SplattedExpr) { + QualType DestElemTy = VectorTy->castAs()->getElementType(); + + if (DestElemTy == SplattedExpr->getType()) + return SplattedExpr; + + assert(DestElemTy->isFloatingType() || + DestElemTy->isIntegralOrEnumerationType()); + + CastKind CK; + if (VectorTy->isExtVectorType() && SplattedExpr->getType()->isBooleanType()) { + // OpenCL requires that we convert `true` boolean expressions to -1, but + // only when splatting vectors. + if (DestElemTy->isFloatingType()) { + // To avoid having to have a CK_BooleanToSignedFloating cast kind, we cast + // in two steps: boolean to signed integral, then to floating. + ExprResult CastExprRes = ImpCastExprToType(SplattedExpr, Context.IntTy, + CK_BooleanToSignedIntegral); + SplattedExpr = CastExprRes.get(); + CK = CK_IntegralToFloating; + } else { + CK = CK_BooleanToSignedIntegral; + } + } else { + ExprResult CastExprRes = SplattedExpr; + CK = PrepareScalarCast(CastExprRes, DestElemTy); + if (CastExprRes.isInvalid()) + return ExprError(); + SplattedExpr = CastExprRes.get(); + } + return ImpCastExprToType(SplattedExpr, DestElemTy, CK); +} + ExprResult Sema::CheckExtVectorCast(SourceRange R, QualType DestTy, Expr *CastExpr, CastKind &Kind) { assert(DestTy->isExtVectorType() && "Not an extended vector type!"); @@ -5613,15 +5665,8 @@ ExprResult Sema::CheckExtVectorCast(SourceRange R, QualType DestTy, diag::err_invalid_conversion_between_vector_and_scalar) << DestTy << SrcTy << R; - QualType DestElemTy = DestTy->getAs()->getElementType(); - ExprResult CastExprRes = CastExpr; - CastKind CK = PrepareScalarCast(CastExprRes, DestElemTy); - if (CastExprRes.isInvalid()) - return ExprError(); - CastExpr = ImpCastExprToType(CastExprRes.get(), DestElemTy, CK).get(); - Kind = CK_VectorSplat; - return CastExpr; + return prepareVectorSplat(DestTy, CastExpr); } ExprResult @@ -6960,13 +7005,9 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS, if (RHSType->isExtVectorType()) return Incompatible; if (RHSType->isArithmeticType()) { - // CK_VectorSplat does T -> vector T, so first cast to the - // element type. - QualType elType = cast(LHSType)->getElementType(); - if (elType != RHSType && ConvertRHS) { - Kind = PrepareScalarCast(RHS, elType); - RHS = ImpCastExprToType(RHS.get(), elType, Kind); - } + // CK_VectorSplat does T -> vector T, so first cast to the element type. + if (ConvertRHS) + RHS = prepareVectorSplat(LHSType, RHS.get()); Kind = CK_VectorSplat; return Compatible; } @@ -8184,7 +8225,7 @@ static QualType checkOpenCLVectorShift(Sema &S, if (RHS.isInvalid()) return QualType(); QualType LHSType = LHS.get()->getType(); - const VectorType *LHSVecTy = LHSType->getAs(); + const VectorType *LHSVecTy = LHSType->castAs(); QualType LHSEleType = LHSVecTy->getElementType(); // Note that RHS might not be a vector. @@ -13121,6 +13162,7 @@ bool Sema::tryCaptureVariable( case Type::ObjCObject: case Type::ObjCInterface: case Type::ObjCObjectPointer: + case Type::Pipe: llvm_unreachable("type class is never variably-modified!"); case Type::Adjusted: QTy = cast(Ty)->getOriginalType(); diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 2ad595f3a814..38fbea18d790 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -3353,20 +3353,13 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, VK_RValue, /*BasePath=*/nullptr, CCK).get(); break; - case ICK_Vector_Splat: + case ICK_Vector_Splat: { // Vector splat from any arithmetic type to a vector. - // Cast to the element type. - { - QualType elType = ToType->getAs()->getElementType(); - if (elType != From->getType()) { - ExprResult E = From; - From = ImpCastExprToType(From, elType, - PrepareScalarCast(E, elType)).get(); - } - From = ImpCastExprToType(From, ToType, CK_VectorSplat, - VK_RValue, /*BasePath=*/nullptr, CCK).get(); - } + Expr *Elem = prepareVectorSplat(ToType, From).get(); + From = ImpCastExprToType(Elem, ToType, CK_VectorSplat, VK_RValue, + /*BasePath=*/nullptr, CCK).get(); break; + } case ICK_Complex_Real: // Case 1. x -> _Complex y diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index 57a08b94f5e8..1d86ca35412e 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -319,6 +319,7 @@ ExprResult Sema::BuildObjCNumericLiteral(SourceLocation AtLoc, Expr *Number) { // to use to determine the Objective-c literal kind. switch (Char->getKind()) { case CharacterLiteral::Ascii: + case CharacterLiteral::UTF8: NumberType = Context.CharTy; break; @@ -577,6 +578,7 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) { // to use to determine the Objective-c literal kind. switch (Char->getKind()) { case CharacterLiteral::Ascii: + case CharacterLiteral::UTF8: ValueType = Context.CharTy; break; diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 481ae6cd55b1..45dc2e33da93 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -650,6 +650,13 @@ void LookupResult::print(raw_ostream &Out) { } } +LLVM_DUMP_METHOD void LookupResult::dump() { + llvm::errs() << "lookup results for " << getLookupName().getAsString() + << ":\n"; + for (NamedDecl *D : *this) + D->dump(); +} + /// \brief Lookup a builtin function, when name lookup would otherwise /// fail. static bool LookupBuiltin(Sema &S, LookupResult &R) { @@ -2616,6 +2623,9 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) { case Type::Atomic: T = cast(T)->getValueType().getTypePtr(); continue; + case Type::Pipe: + T = cast(T)->getElementType().getTypePtr(); + continue; } if (Queue.empty()) @@ -4988,3 +4998,12 @@ const Sema::TypoExprState &Sema::getTypoExprState(TypoExpr *TE) const { void Sema::clearDelayedTypo(TypoExpr *TE) { DelayedTypos.erase(TE); } + +void Sema::ActOnPragmaDump(Scope *S, SourceLocation IILoc, IdentifierInfo *II) { + DeclarationNameInfo Name(II, IILoc); + LookupResult R(*this, Name, LookupAnyName, Sema::NotForRedeclaration); + R.suppressDiagnostics(); + R.setHideTags(false); + LookupName(R, S); + R.dump(); +} diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index e0c10e4479e2..663da0c0e804 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -258,6 +258,7 @@ static const Expr *IgnoreNarrowingConversion(const Expr *Converted) { case CK_IntegralCast: case CK_IntegralToBoolean: case CK_IntegralToFloating: + case CK_BooleanToSignedIntegral: case CK_FloatingToIntegral: case CK_FloatingToBoolean: case CK_FloatingCast: @@ -9643,6 +9644,13 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand, case ovl_fail_enable_if: return DiagnoseFailedEnableIfAttr(S, Cand); + + case ovl_fail_addr_not_available: { + bool Available = checkAddressOfCandidateIsAvailable(S, Cand->Function); + (void)Available; + assert(!Available); + break; + } } } @@ -11245,6 +11253,17 @@ static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, return ExprError(); } +static void markUnaddressableCandidatesUnviable(Sema &S, + OverloadCandidateSet &CS) { + for (auto I = CS.begin(), E = CS.end(); I != E; ++I) { + if (I->Viable && + !S.checkAddressOfFunctionIsAvailable(I->Function, /*Complain=*/false)) { + I->Viable = false; + I->FailureKind = ovl_fail_addr_not_available; + } + } +} + /// BuildOverloadedCallExpr - Given the call expression that calls Fn /// (which eventually refers to the declaration Func) and the call /// arguments Args/NumArgs, attempt to resolve the function call down @@ -11257,7 +11276,8 @@ ExprResult Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, MultiExprArg Args, SourceLocation RParenLoc, Expr *ExecConfig, - bool AllowTypoCorrection) { + bool AllowTypoCorrection, + bool CalleesAddressIsTaken) { OverloadCandidateSet CandidateSet(Fn->getExprLoc(), OverloadCandidateSet::CSK_Normal); ExprResult result; @@ -11266,6 +11286,11 @@ ExprResult Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, &result)) return result; + // If the user handed us something like `(&Foo)(Bar)`, we need to ensure that + // functions that aren't addressible are considered unviable. + if (CalleesAddressIsTaken) + markUnaddressableCandidatesUnviable(*this, CandidateSet); + OverloadCandidateSet::iterator Best; OverloadingResult OverloadResult = CandidateSet.BestViableFunction(*this, Fn->getLocStart(), Best); diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 6cc85883345d..57156078c80b 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -4184,6 +4184,10 @@ bool UnnamedLocalNoLinkageFinder::VisitAtomicType(const AtomicType* T) { return Visit(T->getValueType()); } +bool UnnamedLocalNoLinkageFinder::VisitPipeType(const PipeType* T) { + return false; +} + bool UnnamedLocalNoLinkageFinder::VisitTagDecl(const TagDecl *Tag) { if (Tag->getDeclContext()->isFunctionOrMethod()) { S.Diag(SR.getBegin(), @@ -5503,6 +5507,8 @@ Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg, Expr *E; if (T->isAnyCharacterType()) { + // This does not need to handle u8 character literals because those are + // of type char, and so can also be covered by an ASCII character literal. CharacterLiteral::CharacterKind Kind; if (T->isWideCharType()) Kind = CharacterLiteral::Wide; diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index cd54920b08cf..71faafc6bc12 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -1652,6 +1652,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S, case Type::Auto: case Type::DependentTemplateSpecialization: case Type::PackExpansion: + case Type::Pipe: // No template argument deduction for these types return Sema::TDK_Success; } @@ -4964,6 +4965,7 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T, case Type::ObjCObject: case Type::ObjCObjectPointer: case Type::UnresolvedUsing: + case Type::Pipe: #define TYPE(Class, Base) #define ABSTRACT_TYPE(Class, Base) #define DEPENDENT_TYPE(Class, Base) diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp index 61052f06c834..cb67d71f9e59 100644 --- a/lib/Sema/SemaTemplateVariadic.cpp +++ b/lib/Sema/SemaTemplateVariadic.cpp @@ -750,6 +750,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) { case DeclaratorChunk::Pointer: case DeclaratorChunk::Reference: case DeclaratorChunk::Paren: + case DeclaratorChunk::Pipe: case DeclaratorChunk::BlockPointer: // These declarator chunks cannot contain any parameter packs. break; diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index c70568c23b57..f6ad132cde83 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -335,6 +335,7 @@ static DeclaratorChunk *maybeMovePastReturnType(Declarator &declarator, case DeclaratorChunk::Array: case DeclaratorChunk::Reference: case DeclaratorChunk::MemberPointer: + case DeclaratorChunk::Pipe: return result; // If we do find a function declarator, scan inwards from that, @@ -347,6 +348,7 @@ static DeclaratorChunk *maybeMovePastReturnType(Declarator &declarator, case DeclaratorChunk::Array: case DeclaratorChunk::Function: case DeclaratorChunk::Reference: + case DeclaratorChunk::Pipe: continue; case DeclaratorChunk::MemberPointer: @@ -427,6 +429,7 @@ static void distributeObjCPointerTypeAttr(TypeProcessingState &state, // Don't walk through these. case DeclaratorChunk::Reference: case DeclaratorChunk::MemberPointer: + case DeclaratorChunk::Pipe: goto error; } } @@ -459,6 +462,7 @@ distributeObjCPointerTypeAttrFromDeclarator(TypeProcessingState &state, case DeclaratorChunk::MemberPointer: case DeclaratorChunk::Paren: case DeclaratorChunk::Array: + case DeclaratorChunk::Pipe: continue; case DeclaratorChunk::Function: @@ -520,6 +524,7 @@ static void distributeFunctionTypeAttr(TypeProcessingState &state, case DeclaratorChunk::Array: case DeclaratorChunk::Reference: case DeclaratorChunk::MemberPointer: + case DeclaratorChunk::Pipe: continue; } } @@ -1272,6 +1277,10 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { // value being declared, poison it as invalid so we don't get chains of // errors. declarator.setInvalidType(true); + } else if (S.getLangOpts().OpenCLVersion >= 200 && DS.isTypeSpecPipe()){ + S.Diag(DeclLoc, diag::err_missing_actual_pipe_type) + << DS.getSourceRange(); + declarator.setInvalidType(true); } else { S.Diag(DeclLoc, diag::ext_missing_type_specifier) << DS.getSourceRange(); @@ -1564,7 +1573,9 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { // Apply any type attributes from the decl spec. This may cause the // list of type attributes to be temporarily saved while the type // attributes are pushed around. - processTypeAttrs(state, Result, TAL_DeclSpec, DS.getAttributes().getList()); + // pipe attributes will be handled later ( at GetFullTypeForDeclarator ) + if (!DS.isTypeSpecPipe()) + processTypeAttrs(state, Result, TAL_DeclSpec, DS.getAttributes().getList()); // Apply const/volatile/restrict qualifiers to T. if (unsigned TypeQuals = DS.getTypeQualifiers()) { @@ -1924,6 +1935,21 @@ QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue, return Context.getRValueReferenceType(T); } +/// \brief Build a Pipe type. +/// +/// \param T The type to which we'll be building a Pipe. +/// +/// \param Loc We do not use it for now. +/// +/// \returns A suitable pipe type, if there are no errors. Otherwise, returns a +/// NULL type. +QualType Sema::BuildPipeType(QualType T, SourceLocation Loc) { + assert(!T->isObjCObjectType() && "Should build ObjCObjectPointerType"); + + // Build the pipe type. + return Context.getPipeType(T); +} + /// Check whether the specified array size makes the array type a VLA. If so, /// return true, if not, return the size of the array in SizeVal. static bool isArraySizeVLA(Sema &S, Expr *ArraySize, llvm::APSInt &SizeVal) { @@ -2393,6 +2419,7 @@ static void inferARCWriteback(TypeProcessingState &state, case DeclaratorChunk::Array: // suppress if written (id[])? case DeclaratorChunk::Function: case DeclaratorChunk::MemberPointer: + case DeclaratorChunk::Pipe: return; } } @@ -2532,6 +2559,7 @@ static void diagnoseRedundantReturnTypeQualifiers(Sema &S, QualType RetTy, case DeclaratorChunk::Reference: case DeclaratorChunk::Array: case DeclaratorChunk::MemberPointer: + case DeclaratorChunk::Pipe: // FIXME: We can't currently provide an accurate source location and a // fix-it hint for these. unsigned AtomicQual = RetTy->isAtomicType() ? DeclSpec::TQ_atomic : 0; @@ -3057,6 +3085,7 @@ static PointerDeclaratorKind classifyPointerDeclarator(Sema &S, switch (chunk.Kind) { case DeclaratorChunk::Array: case DeclaratorChunk::Function: + case DeclaratorChunk::Pipe: break; case DeclaratorChunk::BlockPointer: @@ -3305,6 +3334,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, case DeclaratorChunk::Array: DiagKind = 2; break; + case DeclaratorChunk::Pipe: + break; } S.Diag(DeclChunk.Loc, DiagId) << DiagKind; @@ -3370,6 +3401,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, switch (chunk.Kind) { case DeclaratorChunk::Array: case DeclaratorChunk::Function: + case DeclaratorChunk::Pipe: break; case DeclaratorChunk::BlockPointer: @@ -3689,6 +3721,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, break; case DeclaratorChunk::Function: case DeclaratorChunk::BlockPointer: + case DeclaratorChunk::Pipe: // These are invalid anyway, so just ignore. break; } @@ -4038,7 +4071,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, break; } - case DeclaratorChunk::MemberPointer: + case DeclaratorChunk::MemberPointer: { // The scope spec must refer to a class, or be dependent. CXXScopeSpec &SS = DeclType.Mem.Scope(); QualType ClsType; @@ -4098,6 +4131,12 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, break; } + case DeclaratorChunk::Pipe: { + T = S.BuildPipeType(T, DeclType.Loc ); + break; + } + } + if (T.isNull()) { D.setInvalidType(true); T = Context.IntTy; @@ -4392,6 +4431,7 @@ static void transferARCOwnership(TypeProcessingState &state, case DeclaratorChunk::Function: case DeclaratorChunk::MemberPointer: + case DeclaratorChunk::Pipe: return; } } @@ -4682,6 +4722,14 @@ namespace { } } + void VisitPipeTypeLoc(PipeTypeLoc TL) { + TL.setKWLoc(DS.getTypeSpecTypeLoc()); + + TypeSourceInfo *TInfo = 0; + Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo); + TL.getValueLoc().initializeFullCopy(TInfo->getTypeLoc()); + } + void VisitTypeLoc(TypeLoc TL) { // FIXME: add other typespec types and change this to an assert. TL.initialize(Context, DS.getTypeSpecTypeLoc()); @@ -4802,6 +4850,10 @@ namespace { TL.setLParenLoc(Chunk.Loc); TL.setRParenLoc(Chunk.EndLoc); } + void VisitPipeTypeLoc(PipeTypeLoc TL) { + assert(Chunk.Kind == DeclaratorChunk::Pipe); + TL.setKWLoc(Chunk.Loc); + } void VisitTypeLoc(TypeLoc TL) { llvm_unreachable("unsupported TypeLoc kind in declarator!"); @@ -4815,6 +4867,7 @@ static void fillAtomicQualLoc(AtomicTypeLoc ATL, const DeclaratorChunk &Chunk) { case DeclaratorChunk::Function: case DeclaratorChunk::Array: case DeclaratorChunk::Paren: + case DeclaratorChunk::Pipe: llvm_unreachable("cannot be _Atomic qualified"); case DeclaratorChunk::Pointer: @@ -5738,6 +5791,7 @@ static bool distributeNullabilityTypeAttr(TypeProcessingState &state, // Don't walk through these. case DeclaratorChunk::Reference: + case DeclaratorChunk::Pipe: return false; } } diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index e0a9653eb93b..935304fe4076 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -1046,6 +1046,9 @@ public: /// Subclasses may override this routine to provide different behavior. QualType RebuildAtomicType(QualType ValueType, SourceLocation KWLoc); + /// \brief Build a new pipe type given its value type. + QualType RebuildPipeType(QualType ValueType, SourceLocation KWLoc); + /// \brief Build a new template name given a nested name specifier, a flag /// indicating whether the "template" keyword was provided, and the template /// that the template name refers to. @@ -3580,7 +3583,7 @@ void TreeTransform::InventTemplateArgumentLoc( case TemplateArgument::Template: case TemplateArgument::TemplateExpansion: { NestedNameSpecifierLocBuilder Builder; - TemplateName Template = Arg.getAsTemplate(); + TemplateName Template = Arg.getAsTemplateOrTemplatePattern(); if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) Builder.MakeTrivial(SemaRef.Context, DTN->getQualifier(), Loc); else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) @@ -5324,6 +5327,26 @@ QualType TreeTransform::TransformAtomicType(TypeLocBuilder &TLB, return Result; } +template +QualType TreeTransform::TransformPipeType(TypeLocBuilder &TLB, + PipeTypeLoc TL) { + QualType ValueType = getDerived().TransformType(TLB, TL.getValueLoc()); + if (ValueType.isNull()) + return QualType(); + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || ValueType != TL.getValueLoc().getType()) { + Result = getDerived().RebuildPipeType(ValueType, TL.getKWLoc()); + if (Result.isNull()) + return QualType(); + } + + PipeTypeLoc NewTL = TLB.push(Result); + NewTL.setKWLoc(TL.getKWLoc()); + + return Result; +} + /// \brief Simple iterator that traverses the template arguments in a /// container that provides a \c getArgLoc() member function. /// @@ -6128,7 +6151,7 @@ TreeTransform::TransformIfStmt(IfStmt *S) { } } - Sema::FullExprArg FullCond(getSema().MakeFullExpr(Cond.get())); + Sema::FullExprArg FullCond(getSema().MakeFullExpr(Cond.get(), S->getIfLoc())); if (!S->getConditionVariable() && S->getCond() && !FullCond.get()) return StmtError(); @@ -6223,7 +6246,8 @@ TreeTransform::TransformWhileStmt(WhileStmt *S) { } } - Sema::FullExprArg FullCond(getSema().MakeFullExpr(Cond.get())); + Sema::FullExprArg FullCond( + getSema().MakeFullExpr(Cond.get(), S->getWhileLoc())); if (!S->getConditionVariable() && S->getCond() && !FullCond.get()) return StmtError(); @@ -6307,7 +6331,8 @@ TreeTransform::TransformForStmt(ForStmt *S) { } } - Sema::FullExprArg FullCond(getSema().MakeFullExpr(Cond.get())); + Sema::FullExprArg FullCond( + getSema().MakeFullExpr(Cond.get(), S->getForLoc())); if (!S->getConditionVariable() && S->getCond() && !FullCond.get()) return StmtError(); @@ -11347,6 +11372,12 @@ QualType TreeTransform::RebuildAtomicType(QualType ValueType, return SemaRef.BuildAtomicType(ValueType, KWLoc); } +template +QualType TreeTransform::RebuildPipeType(QualType ValueType, + SourceLocation KWLoc) { + return SemaRef.BuildPipeType(ValueType, KWLoc); +} + template TemplateName TreeTransform::RebuildTemplateName(CXXScopeSpec &SS, diff --git a/lib/Serialization/ASTCommon.h b/lib/Serialization/ASTCommon.h index e59bc891f9b9..64f583c98728 100644 --- a/lib/Serialization/ASTCommon.h +++ b/lib/Serialization/ASTCommon.h @@ -29,6 +29,7 @@ enum DeclUpdateKind { UPD_CXX_ADDED_FUNCTION_DEFINITION, UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER, UPD_CXX_INSTANTIATED_CLASS_DEFINITION, + UPD_CXX_INSTANTIATED_DEFAULT_ARGUMENT, UPD_CXX_RESOLVED_DTOR_DELETE, UPD_CXX_RESOLVED_EXCEPTION_SPEC, UPD_CXX_DEDUCED_RETURN_TYPE, diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index a279475eeafb..833ff57e4d0b 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -5640,6 +5640,17 @@ QualType ASTReader::readTypeRecord(unsigned Index) { QualType ValueType = readType(*Loc.F, Record, Idx); return Context.getAtomicType(ValueType); } + + case TYPE_PIPE: { + if (Record.size() != 1) { + Error("Incorrect encoding of pipe type"); + return QualType(); + } + + // Reading the pipe element type. + QualType ElementType = readType(*Loc.F, Record, Idx); + return Context.getPipeType(ElementType); + } } llvm_unreachable("Invalid TypeCode!"); } @@ -5911,6 +5922,9 @@ void TypeLocReader::VisitAtomicTypeLoc(AtomicTypeLoc TL) { TL.setLParenLoc(ReadSourceLocation(Record, Idx)); TL.setRParenLoc(ReadSourceLocation(Record, Idx)); } +void TypeLocReader::VisitPipeTypeLoc(PipeTypeLoc TL) { + TL.setKWLoc(ReadSourceLocation(Record, Idx)); +} TypeSourceInfo *ASTReader::GetTypeSourceInfo(ModuleFile &F, const RecordData &Record, diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 8fb110e4551d..5bf95f878d49 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -3626,6 +3626,21 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile, Reader.ReadSourceLocation(ModuleFile, Record, Idx)); break; + case UPD_CXX_INSTANTIATED_DEFAULT_ARGUMENT: { + auto Param = cast(D); + + // We have to read the default argument regardless of whether we use it + // so that hypothetical further update records aren't messed up. + // TODO: Add a function to skip over the next expr record. + auto DefaultArg = Reader.ReadExpr(F); + + // Only apply the update if the parameter still has an uninstantiated + // default argument. + if (Param->hasUninstantiatedDefaultArg()) + Param->setDefaultArg(DefaultArg); + break; + } + case UPD_CXX_ADDED_FUNCTION_DEFINITION: { FunctionDecl *FD = cast(D); if (Reader.PendingBodies[FD]) { diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp index bc678aff7861..ad81ac844209 100644 --- a/lib/Serialization/ASTReaderStmt.cpp +++ b/lib/Serialization/ASTReaderStmt.cpp @@ -1364,10 +1364,7 @@ void ASTStmtReader::VisitCXXThrowExpr(CXXThrowExpr *E) { void ASTStmtReader::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { VisitExpr(E); - - assert((bool)Record[Idx] == E->Param.getInt() && "We messed up at creation ?"); - ++Idx; // HasOtherExprStored and SubExpr was handled during creation. - E->Param.setPointer(ReadDeclAs(Record, Idx)); + E->Param = ReadDeclAs(Record, Idx); E->Loc = ReadSourceLocation(Record, Idx); } @@ -3205,16 +3202,9 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { case EXPR_CXX_THROW: S = new (Context) CXXThrowExpr(Empty); break; - case EXPR_CXX_DEFAULT_ARG: { - bool HasOtherExprStored = Record[ASTStmtReader::NumExprFields]; - if (HasOtherExprStored) { - Expr *SubExpr = ReadSubExpr(); - S = CXXDefaultArgExpr::Create(Context, SourceLocation(), nullptr, - SubExpr); - } else - S = new (Context) CXXDefaultArgExpr(Empty); + case EXPR_CXX_DEFAULT_ARG: + S = new (Context) CXXDefaultArgExpr(Empty); break; - } case EXPR_CXX_DEFAULT_INIT: S = new (Context) CXXDefaultInitExpr(Empty); break; diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 0f50d7a42eab..ec04cd6c1fa9 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -446,6 +446,12 @@ ASTTypeWriter::VisitAtomicType(const AtomicType *T) { Code = TYPE_ATOMIC; } +void +ASTTypeWriter::VisitPipeType(const PipeType *T) { + Writer.AddTypeRef(T->getElementType(), Record); + Code = TYPE_PIPE; +} + namespace { class TypeLocWriter : public TypeLocVisitor { @@ -672,6 +678,9 @@ void TypeLocWriter::VisitAtomicTypeLoc(AtomicTypeLoc TL) { Writer.AddSourceLocation(TL.getLParenLoc(), Record); Writer.AddSourceLocation(TL.getRParenLoc(), Record); } +void TypeLocWriter::VisitPipeTypeLoc(PipeTypeLoc TL) { + Writer.AddSourceLocation(TL.getKWLoc(), Record); +} void ASTWriter::WriteTypeAbbrevs() { using namespace llvm; @@ -4611,6 +4620,11 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) { AddSourceLocation(Update.getLoc(), Record); break; + case UPD_CXX_INSTANTIATED_DEFAULT_ARGUMENT: + AddStmt(const_cast( + cast(Update.getDecl())->getDefaultArg())); + break; + case UPD_CXX_INSTANTIATED_CLASS_DEFINITION: { auto *RD = cast(D); UpdatedDeclContexts.insert(RD->getPrimaryContext()); @@ -5779,6 +5793,15 @@ void ASTWriter::StaticDataMemberInstantiated(const VarDecl *D) { D->getMemberSpecializationInfo()->getPointOfInstantiation())); } +void ASTWriter::DefaultArgumentInstantiated(const ParmVarDecl *D) { + assert(!WritingAST && "Already writing the AST!"); + if (!D->isFromASTFile()) + return; + + DeclUpdates[D].push_back( + DeclUpdate(UPD_CXX_INSTANTIATED_DEFAULT_ARGUMENT, D)); +} + void ASTWriter::AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD, const ObjCInterfaceDecl *IFD) { assert(!WritingAST && "Already writing the AST!"); diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index 20ca6d6fd512..54bba282ab8d 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -2033,7 +2033,7 @@ void ASTWriter::WriteDeclAbbrevs() { //Character Literal Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // getValue Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Location - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // getKind + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // getKind CharacterLiteralAbbrev = Stream.EmitAbbrev(Abv); // Abbreviation for EXPR_IMPLICIT_CAST diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp index e52ed052d3bc..000a2185f5f0 100644 --- a/lib/Serialization/ASTWriterStmt.cpp +++ b/lib/Serialization/ASTWriterStmt.cpp @@ -1336,15 +1336,8 @@ void ASTStmtWriter::VisitCXXThrowExpr(CXXThrowExpr *E) { void ASTStmtWriter::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { VisitExpr(E); - - bool HasOtherExprStored = E->Param.getInt(); - // Store these first, the reader reads them before creation. - Record.push_back(HasOtherExprStored); - if (HasOtherExprStored) - Writer.AddStmt(E->getExpr()); Writer.AddDeclRef(E->getParam(), Record); Writer.AddSourceLocation(E->getUsedLocation(), Record); - Code = serialization::EXPR_CXX_DEFAULT_ARG; } diff --git a/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/lib/StaticAnalyzer/Checkers/CStringChecker.cpp index 5d78d9b02e6b..17537445d66c 100644 --- a/lib/StaticAnalyzer/Checkers/CStringChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/CStringChecker.cpp @@ -948,15 +948,15 @@ bool CStringChecker::SummarizeRegion(raw_ostream &os, ASTContext &Ctx, const TypedValueRegion *TVR = dyn_cast(MR); switch (MR->getKind()) { - case MemRegion::FunctionTextRegionKind: { - const NamedDecl *FD = cast(MR)->getDecl(); + case MemRegion::FunctionCodeRegionKind: { + const NamedDecl *FD = cast(MR)->getDecl(); if (FD) os << "the address of the function '" << *FD << '\''; else os << "the address of a function"; return true; } - case MemRegion::BlockTextRegionKind: + case MemRegion::BlockCodeRegionKind: os << "block text"; return true; case MemRegion::BlockDataRegionKind: diff --git a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index ce2c19409dc1..fee030feb6d2 100644 --- a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -1513,15 +1513,15 @@ bool MallocChecker::SummarizeValue(raw_ostream &os, SVal V) { bool MallocChecker::SummarizeRegion(raw_ostream &os, const MemRegion *MR) { switch (MR->getKind()) { - case MemRegion::FunctionTextRegionKind: { - const NamedDecl *FD = cast(MR)->getDecl(); + case MemRegion::FunctionCodeRegionKind: { + const NamedDecl *FD = cast(MR)->getDecl(); if (FD) os << "the address of the function '" << *FD << '\''; else os << "the address of a function"; return true; } - case MemRegion::BlockTextRegionKind: + case MemRegion::BlockCodeRegionKind: os << "block text"; return true; case MemRegion::BlockDataRegionKind: diff --git a/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/lib/StaticAnalyzer/Core/ExprEngineC.cpp index a5b58710b215..175225ba0de2 100644 --- a/lib/StaticAnalyzer/Core/ExprEngineC.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngineC.cpp @@ -316,7 +316,7 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, case CK_ArrayToPointerDecay: case CK_BitCast: case CK_AddressSpaceConversion: - case CK_IntegralCast: + case CK_BooleanToSignedIntegral: case CK_NullToPointer: case CK_IntegralToPointer: case CK_PointerToIntegral: @@ -345,6 +345,17 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, // Delegate to SValBuilder to process. SVal V = state->getSVal(Ex, LCtx); V = svalBuilder.evalCast(V, T, ExTy); + // Negate the result if we're treating the boolean as a signed i1 + if (CastE->getCastKind() == CK_BooleanToSignedIntegral) + V = evalMinus(V); + state = state->BindExpr(CastE, LCtx, V); + Bldr.generateNode(CastE, Pred, state); + continue; + } + case CK_IntegralCast: { + // Delegate to SValBuilder to process. + SVal V = state->getSVal(Ex, LCtx); + V = svalBuilder.evalIntegralCast(state, V, T, ExTy); state = state->BindExpr(CastE, LCtx, V); Bldr.generateNode(CastE, Pred, state); continue; diff --git a/lib/StaticAnalyzer/Core/MemRegion.cpp b/lib/StaticAnalyzer/Core/MemRegion.cpp index ad3f396e39a1..30052ccacee4 100644 --- a/lib/StaticAnalyzer/Core/MemRegion.cpp +++ b/lib/StaticAnalyzer/Core/MemRegion.cpp @@ -245,7 +245,7 @@ QualType CXXBaseObjectRegion::getValueType() const { // FoldingSet profiling. //===----------------------------------------------------------------------===// -void MemSpaceRegion::Profile(llvm::FoldingSetNodeID& ID) const { +void MemSpaceRegion::Profile(llvm::FoldingSetNodeID &ID) const { ID.AddInteger((unsigned)getKind()); } @@ -357,31 +357,31 @@ void ElementRegion::Profile(llvm::FoldingSetNodeID& ID) const { ElementRegion::ProfileRegion(ID, ElementType, Index, superRegion); } -void FunctionTextRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, +void FunctionCodeRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, const NamedDecl *FD, const MemRegion*) { - ID.AddInteger(MemRegion::FunctionTextRegionKind); + ID.AddInteger(MemRegion::FunctionCodeRegionKind); ID.AddPointer(FD); } -void FunctionTextRegion::Profile(llvm::FoldingSetNodeID& ID) const { - FunctionTextRegion::ProfileRegion(ID, FD, superRegion); +void FunctionCodeRegion::Profile(llvm::FoldingSetNodeID& ID) const { + FunctionCodeRegion::ProfileRegion(ID, FD, superRegion); } -void BlockTextRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, +void BlockCodeRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, const BlockDecl *BD, CanQualType, const AnalysisDeclContext *AC, const MemRegion*) { - ID.AddInteger(MemRegion::BlockTextRegionKind); + ID.AddInteger(MemRegion::BlockCodeRegionKind); ID.AddPointer(BD); } -void BlockTextRegion::Profile(llvm::FoldingSetNodeID& ID) const { - BlockTextRegion::ProfileRegion(ID, BD, locTy, AC, superRegion); +void BlockCodeRegion::Profile(llvm::FoldingSetNodeID& ID) const { + BlockCodeRegion::ProfileRegion(ID, BD, locTy, AC, superRegion); } void BlockDataRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, - const BlockTextRegion *BC, + const BlockCodeRegion *BC, const LocationContext *LC, unsigned BlkCount, const MemRegion *sReg) { @@ -457,11 +457,11 @@ void AllocaRegion::dumpToStream(raw_ostream &os) const { os << "alloca{" << (const void*) Ex << ',' << Cnt << '}'; } -void FunctionTextRegion::dumpToStream(raw_ostream &os) const { +void FunctionCodeRegion::dumpToStream(raw_ostream &os) const { os << "code{" << getDecl()->getDeclName().getAsString() << '}'; } -void BlockTextRegion::dumpToStream(raw_ostream &os) const { +void BlockCodeRegion::dumpToStream(raw_ostream &os) const { os << "block_code{" << (const void*) this << '}'; } @@ -533,6 +533,10 @@ void RegionRawOffset::dumpToStream(raw_ostream &os) const { os << "raw_offset{" << getRegion() << ',' << getOffset().getQuantity() << '}'; } +void CodeSpaceRegion::dumpToStream(raw_ostream &os) const { + os << "CodeSpaceRegion"; +} + void StaticGlobalSpaceRegion::dumpToStream(raw_ostream &os) const { os << "StaticGlobalsMemSpace{" << CR << '}'; } @@ -711,11 +715,11 @@ const HeapSpaceRegion *MemRegionManager::getHeapRegion() { return LazyAllocate(heap); } -const MemSpaceRegion *MemRegionManager::getUnknownRegion() { +const UnknownSpaceRegion *MemRegionManager::getUnknownRegion() { return LazyAllocate(unknown); } -const MemSpaceRegion *MemRegionManager::getCodeRegion() { +const CodeSpaceRegion *MemRegionManager::getCodeRegion() { return LazyAllocate(code); } @@ -815,11 +819,11 @@ const VarRegion* MemRegionManager::getVarRegion(const VarDecl *D, const Decl *STCD = STC->getDecl(); if (isa(STCD) || isa(STCD)) sReg = getGlobalsRegion(MemRegion::StaticGlobalSpaceRegionKind, - getFunctionTextRegion(cast(STCD))); + getFunctionCodeRegion(cast(STCD))); else if (const BlockDecl *BD = dyn_cast(STCD)) { // FIXME: The fallback type here is totally bogus -- though it should // never be queried, it will prevent uniquing with the real - // BlockTextRegion. Ideally we'd fix the AST so that we always had a + // BlockCodeRegion. Ideally we'd fix the AST so that we always had a // signature. QualType T; if (const TypeSourceInfo *TSI = BD->getSignatureAsWritten()) @@ -830,8 +834,8 @@ const VarRegion* MemRegionManager::getVarRegion(const VarDecl *D, T = getContext().getFunctionNoProtoType(T); T = getContext().getBlockPointerType(T); - const BlockTextRegion *BTR = - getBlockTextRegion(BD, C.getCanonicalType(T), + const BlockCodeRegion *BTR = + getBlockCodeRegion(BD, C.getCanonicalType(T), STC->getAnalysisDeclContext()); sReg = getGlobalsRegion(MemRegion::StaticGlobalSpaceRegionKind, BTR); @@ -852,7 +856,7 @@ const VarRegion *MemRegionManager::getVarRegion(const VarDecl *D, } const BlockDataRegion * -MemRegionManager::getBlockDataRegion(const BlockTextRegion *BC, +MemRegionManager::getBlockDataRegion(const BlockCodeRegion *BC, const LocationContext *LC, unsigned blockCount) { const MemRegion *sReg = nullptr; @@ -925,15 +929,15 @@ MemRegionManager::getElementRegion(QualType elementType, NonLoc Idx, return R; } -const FunctionTextRegion * -MemRegionManager::getFunctionTextRegion(const NamedDecl *FD) { - return getSubRegion(FD, getCodeRegion()); +const FunctionCodeRegion * +MemRegionManager::getFunctionCodeRegion(const NamedDecl *FD) { + return getSubRegion(FD, getCodeRegion()); } -const BlockTextRegion * -MemRegionManager::getBlockTextRegion(const BlockDecl *BD, CanQualType locTy, +const BlockCodeRegion * +MemRegionManager::getBlockCodeRegion(const BlockDecl *BD, CanQualType locTy, AnalysisDeclContext *AC) { - return getSubRegion(BD, locTy, AC, getCodeRegion()); + return getSubRegion(BD, locTy, AC, getCodeRegion()); } @@ -1196,7 +1200,7 @@ RegionOffset MemRegion::getAsOffset() const { while (1) { switch (R->getKind()) { - case GenericMemSpaceRegionKind: + case CodeSpaceRegionKind: case StackLocalsSpaceRegionKind: case StackArgumentsSpaceRegionKind: case HeapSpaceRegionKind: @@ -1209,8 +1213,8 @@ RegionOffset MemRegion::getAsOffset() const { assert(Offset == 0 && !SymbolicOffsetBase); goto Finish; - case FunctionTextRegionKind: - case BlockTextRegionKind: + case FunctionCodeRegionKind: + case BlockCodeRegionKind: case BlockDataRegionKind: // These will never have bindings, but may end up having values requested // if the user does some strange casting. diff --git a/lib/StaticAnalyzer/Core/ProgramState.cpp b/lib/StaticAnalyzer/Core/ProgramState.cpp index 4f9ad9ebccd9..100fa75c5f42 100644 --- a/lib/StaticAnalyzer/Core/ProgramState.cpp +++ b/lib/StaticAnalyzer/Core/ProgramState.cpp @@ -536,19 +536,19 @@ bool ScanReachableSymbols::scan(const SymExpr *sym) { // TODO: should be rewritten using SymExpr::symbol_iterator. switch (sym->getKind()) { - case SymExpr::RegionValueKind: - case SymExpr::ConjuredKind: - case SymExpr::DerivedKind: - case SymExpr::ExtentKind: - case SymExpr::MetadataKind: + case SymExpr::SymbolRegionValueKind: + case SymExpr::SymbolConjuredKind: + case SymExpr::SymbolDerivedKind: + case SymExpr::SymbolExtentKind: + case SymExpr::SymbolMetadataKind: break; - case SymExpr::CastSymbolKind: + case SymExpr::SymbolCastKind: return scan(cast(sym)->getOperand()); - case SymExpr::SymIntKind: + case SymExpr::SymIntExprKind: return scan(cast(sym)->getLHS()); - case SymExpr::IntSymKind: + case SymExpr::IntSymExprKind: return scan(cast(sym)->getRHS()); - case SymExpr::SymSymKind: { + case SymExpr::SymSymExprKind: { const SymSymExpr *x = cast(sym); return scan(x->getLHS()) && scan(x->getRHS()); } diff --git a/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp b/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp index 0a2b2e64a142..77b0ad32b6b7 100644 --- a/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp +++ b/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp @@ -171,7 +171,7 @@ private: case APSIntType::RTR_Below: // The entire range is outside the symbol's set of possible values. // If this is a conventionally-ordered range, the state is infeasible. - if (Lower < Upper) + if (Lower <= Upper) return false; // However, if the range wraps around, it spans all possible values. @@ -222,7 +222,7 @@ private: case APSIntType::RTR_Above: // The entire range is outside the symbol's set of possible values. // If this is a conventionally-ordered range, the state is infeasible. - if (Lower < Upper) + if (Lower <= Upper) return false; // However, if the range wraps around, it spans all possible values. diff --git a/lib/StaticAnalyzer/Core/SValBuilder.cpp b/lib/StaticAnalyzer/Core/SValBuilder.cpp index cdae04068e1d..18315225a99d 100644 --- a/lib/StaticAnalyzer/Core/SValBuilder.cpp +++ b/lib/StaticAnalyzer/Core/SValBuilder.cpp @@ -214,15 +214,15 @@ SValBuilder::getDerivedRegionValueSymbolVal(SymbolRef parentSymbol, } DefinedSVal SValBuilder::getFunctionPointer(const FunctionDecl *func) { - return loc::MemRegionVal(MemMgr.getFunctionTextRegion(func)); + return loc::MemRegionVal(MemMgr.getFunctionCodeRegion(func)); } DefinedSVal SValBuilder::getBlockPointer(const BlockDecl *block, CanQualType locTy, const LocationContext *locContext, unsigned blockCount) { - const BlockTextRegion *BC = - MemMgr.getBlockTextRegion(block, locTy, locContext->getAnalysisDeclContext()); + const BlockCodeRegion *BC = + MemMgr.getBlockCodeRegion(block, locTy, locContext->getAnalysisDeclContext()); const BlockDataRegion *BD = MemMgr.getBlockDataRegion(BC, locContext, blockCount); return loc::MemRegionVal(BD); @@ -423,6 +423,45 @@ static bool shouldBeModeledWithNoOp(ASTContext &Context, QualType ToTy, return true; } +// Handles casts of type CK_IntegralCast. +// At the moment, this function will redirect to evalCast, except when the range +// of the original value is known to be greater than the max of the target type. +SVal SValBuilder::evalIntegralCast(ProgramStateRef state, SVal val, + QualType castTy, QualType originalTy) { + + // No truncations if target type is big enough. + if (getContext().getTypeSize(castTy) >= getContext().getTypeSize(originalTy)) + return evalCast(val, castTy, originalTy); + + const SymExpr *se = val.getAsSymbolicExpression(); + if (!se) // Let evalCast handle non symbolic expressions. + return evalCast(val, castTy, originalTy); + + // Find the maximum value of the target type. + APSIntType ToType(getContext().getTypeSize(castTy), + castTy->isUnsignedIntegerType()); + llvm::APSInt ToTypeMax = ToType.getMaxValue(); + NonLoc ToTypeMaxVal = + makeIntVal(ToTypeMax.isUnsigned() ? ToTypeMax.getZExtValue() + : ToTypeMax.getSExtValue(), + castTy) + .castAs(); + // Check the range of the symbol being casted against the maximum value of the + // target type. + NonLoc FromVal = val.castAs(); + QualType CmpTy = getConditionType(); + NonLoc CompVal = + evalBinOpNN(state, BO_LT, FromVal, ToTypeMaxVal, CmpTy).castAs(); + ProgramStateRef IsNotTruncated, IsTruncated; + std::tie(IsNotTruncated, IsTruncated) = state->assume(CompVal); + if (!IsNotTruncated && IsTruncated) { + // Symbol is truncated so we evaluate it as a cast. + NonLoc CastVal = makeNonLoc(se, originalTy, castTy); + return CastVal; + } + return evalCast(val, castTy, originalTy); +} + // FIXME: should rewrite according to the cast kind. SVal SValBuilder::evalCast(SVal val, QualType castTy, QualType originalTy) { castTy = Context.getCanonicalType(castTy); diff --git a/lib/StaticAnalyzer/Core/SVals.cpp b/lib/StaticAnalyzer/Core/SVals.cpp index 8de939f47d86..dffee6c8c57b 100644 --- a/lib/StaticAnalyzer/Core/SVals.cpp +++ b/lib/StaticAnalyzer/Core/SVals.cpp @@ -51,7 +51,7 @@ bool SVal::hasConjuredSymbol() const { const FunctionDecl *SVal::getAsFunctionDecl() const { if (Optional X = getAs()) { const MemRegion* R = X->getRegion(); - if (const FunctionTextRegion *CTR = R->getAs()) + if (const FunctionCodeRegion *CTR = R->getAs()) if (const FunctionDecl *FD = dyn_cast(CTR->getDecl())) return FD; } @@ -240,7 +240,7 @@ void SVal::dump() const { dumpToStream(llvm::errs()); } void SVal::dumpToStream(raw_ostream &os) const { switch (getBaseKind()) { - case UnknownKind: + case UnknownValKind: os << "Unknown"; break; case NonLocKind: @@ -249,7 +249,7 @@ void SVal::dumpToStream(raw_ostream &os) const { case LocKind: castAs().dumpToStream(os); break; - case UndefinedKind: + case UndefinedValKind: os << "Undefined"; break; } @@ -313,7 +313,7 @@ void Loc::dumpToStream(raw_ostream &os) const { case loc::GotoLabelKind: os << "&&" << castAs().getLabel()->getName(); break; - case loc::MemRegionKind: + case loc::MemRegionValKind: os << '&' << castAs().getRegion()->getString(); break; default: diff --git a/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp b/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp index a704ce224554..72b852b2e21d 100644 --- a/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp +++ b/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp @@ -141,9 +141,9 @@ SVal SimpleSValBuilder::evalCastFromLoc(Loc val, QualType castTy) { // unless this is a weak function or a symbolic region. if (castTy->isBooleanType()) { switch (val.getSubKind()) { - case loc::MemRegionKind: { + case loc::MemRegionValKind: { const MemRegion *R = val.castAs().getRegion(); - if (const FunctionTextRegion *FTR = dyn_cast(R)) + if (const FunctionCodeRegion *FTR = dyn_cast(R)) if (const FunctionDecl *FD = dyn_cast(FTR->getDecl())) if (FD->isWeak()) // FIXME: Currently we are using an extent symbol here, @@ -689,7 +689,7 @@ SVal SimpleSValBuilder::evalBinOpLL(ProgramStateRef state, // completely unknowable. return UnknownVal(); } - case loc::MemRegionKind: { + case loc::MemRegionValKind: { if (Optional rInt = rhs.getAs()) { // If one of the operands is a symbol and the other is a constant, // build an expression for use by the constraint manager. @@ -718,7 +718,7 @@ SVal SimpleSValBuilder::evalBinOpLL(ProgramStateRef state, // Get both values as regions, if possible. const MemRegion *LeftMR = lhs.getAsRegion(); - assert(LeftMR && "MemRegionKind SVal doesn't have a region!"); + assert(LeftMR && "MemRegionValKind SVal doesn't have a region!"); const MemRegion *RightMR = rhs.getAsRegion(); if (!RightMR) diff --git a/lib/StaticAnalyzer/Core/Store.cpp b/lib/StaticAnalyzer/Core/Store.cpp index 7cdb55a59782..de29f0eedd12 100644 --- a/lib/StaticAnalyzer/Core/Store.cpp +++ b/lib/StaticAnalyzer/Core/Store.cpp @@ -100,7 +100,7 @@ const MemRegion *StoreManager::castRegion(const MemRegion *R, QualType CastToTy) // Process region cast according to the kind of the region being cast. switch (R->getKind()) { case MemRegion::CXXThisRegionKind: - case MemRegion::GenericMemSpaceRegionKind: + case MemRegion::CodeSpaceRegionKind: case MemRegion::StackLocalsSpaceRegionKind: case MemRegion::StackArgumentsSpaceRegionKind: case MemRegion::HeapSpaceRegionKind: @@ -112,8 +112,8 @@ const MemRegion *StoreManager::castRegion(const MemRegion *R, QualType CastToTy) llvm_unreachable("Invalid region cast"); } - case MemRegion::FunctionTextRegionKind: - case MemRegion::BlockTextRegionKind: + case MemRegion::FunctionCodeRegionKind: + case MemRegion::BlockCodeRegionKind: case MemRegion::BlockDataRegionKind: case MemRegion::StringRegionKind: // FIXME: Need to handle arbitrary downcasts. @@ -393,7 +393,7 @@ SVal StoreManager::getLValueFieldOrIvar(const Decl *D, SVal Base) { const MemRegion* BaseR = nullptr; switch (BaseL.getSubKind()) { - case loc::MemRegionKind: + case loc::MemRegionValKind: BaseR = BaseL.castAs().getRegion(); break; diff --git a/lib/StaticAnalyzer/Core/SymbolManager.cpp b/lib/StaticAnalyzer/Core/SymbolManager.cpp index 99b2e147cb49..2dd252c223fd 100644 --- a/lib/StaticAnalyzer/Core/SymbolManager.cpp +++ b/lib/StaticAnalyzer/Core/SymbolManager.cpp @@ -115,22 +115,22 @@ void SymExpr::symbol_iterator::expand() { const SymExpr *SE = itr.pop_back_val(); switch (SE->getKind()) { - case SymExpr::RegionValueKind: - case SymExpr::ConjuredKind: - case SymExpr::DerivedKind: - case SymExpr::ExtentKind: - case SymExpr::MetadataKind: + case SymExpr::SymbolRegionValueKind: + case SymExpr::SymbolConjuredKind: + case SymExpr::SymbolDerivedKind: + case SymExpr::SymbolExtentKind: + case SymExpr::SymbolMetadataKind: return; - case SymExpr::CastSymbolKind: + case SymExpr::SymbolCastKind: itr.push_back(cast(SE)->getOperand()); return; - case SymExpr::SymIntKind: + case SymExpr::SymIntExprKind: itr.push_back(cast(SE)->getLHS()); return; - case SymExpr::IntSymKind: + case SymExpr::IntSymExprKind: itr.push_back(cast(SE)->getRHS()); return; - case SymExpr::SymSymKind: { + case SymExpr::SymSymExprKind: { const SymSymExpr *x = cast(SE); itr.push_back(x->getLHS()); itr.push_back(x->getRHS()); @@ -458,35 +458,35 @@ bool SymbolReaper::isLive(SymbolRef sym) { bool KnownLive; switch (sym->getKind()) { - case SymExpr::RegionValueKind: + case SymExpr::SymbolRegionValueKind: KnownLive = isLiveRegion(cast(sym)->getRegion()); break; - case SymExpr::ConjuredKind: + case SymExpr::SymbolConjuredKind: KnownLive = false; break; - case SymExpr::DerivedKind: + case SymExpr::SymbolDerivedKind: KnownLive = isLive(cast(sym)->getParentSymbol()); break; - case SymExpr::ExtentKind: + case SymExpr::SymbolExtentKind: KnownLive = isLiveRegion(cast(sym)->getRegion()); break; - case SymExpr::MetadataKind: + case SymExpr::SymbolMetadataKind: KnownLive = MetadataInUse.count(sym) && isLiveRegion(cast(sym)->getRegion()); if (KnownLive) MetadataInUse.erase(sym); break; - case SymExpr::SymIntKind: + case SymExpr::SymIntExprKind: KnownLive = isLive(cast(sym)->getLHS()); break; - case SymExpr::IntSymKind: + case SymExpr::IntSymExprKind: KnownLive = isLive(cast(sym)->getRHS()); break; - case SymExpr::SymSymKind: + case SymExpr::SymSymExprKind: KnownLive = isLive(cast(sym)->getLHS()) && isLive(cast(sym)->getRHS()); break; - case SymExpr::CastSymbolKind: + case SymExpr::SymbolCastKind: KnownLive = isLive(cast(sym)->getOperand()); break; } diff --git a/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp index bf85c4ca0c60..d1446855e01f 100644 --- a/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp +++ b/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp @@ -496,10 +496,11 @@ void AnalysisConsumer::HandleDeclsCallGraph(const unsigned LocalTUDeclsSize) { (Mgr->options.InliningMode == All ? nullptr : &VisitedCallees)); // Add the visited callees to the global visited set. - for (SetOfConstDecls::iterator I = VisitedCallees.begin(), - E = VisitedCallees.end(); I != E; ++I) { - Visited.insert(*I); - } + for (const Decl *Callee : VisitedCallees) + // Decls from CallGraph are already canonical. But Decls coming from + // CallExprs may be not. We should canonicalize them manually. + Visited.insert(isa(Callee) ? Callee + : Callee->getCanonicalDecl()); VisitedAsTopLevel.insert(D); } } diff --git a/test/Analysis/inlining/analysis-order.c b/test/Analysis/inlining/analysis-order.c new file mode 100644 index 000000000000..5149818c74fd --- /dev/null +++ b/test/Analysis/inlining/analysis-order.c @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=core.builtin.NoReturnFunctions -analyzer-display-progress %s 2>&1 | FileCheck %s + +// Do not analyze test1() again because it was inlined +void test1(); + +void test2() { + test1(); +} + +void test1() { +} + +// CHECK: analysis-order.c test2 +// CHECK-NEXT: analysis-order.c test1 +// CHECK-NEXT: analysis-order.c test2 diff --git a/test/Analysis/range_casts.c b/test/Analysis/range_casts.c new file mode 100644 index 000000000000..682369cce66f --- /dev/null +++ b/test/Analysis/range_casts.c @@ -0,0 +1,156 @@ +// This test checks that intersecting ranges does not cause 'system is over constrained' assertions in the case of eg: 32 bits unsigned integers getting their range from 64 bits signed integers. +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-store=region -verify %s + +void clang_analyzer_warnIfReached(); + +void f1(long foo) +{ + unsigned index = -1; + if (index < foo) index = foo; + if (index + 1 == 0) // because of foo range, index is in range [0; UINT_MAX] + clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} + else + clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} +} + +void f2(unsigned long foo) +{ + int index = -1; + if (index < foo) index = foo; // index equals ULONG_MAX + if (index + 1 == 0) + clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} + else + clang_analyzer_warnIfReached(); // no-warning +} + +void f3(unsigned long foo) +{ + unsigned index = -1; + if (index < foo) index = foo; + if (index + 1 == 0) + clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} + else + clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} +} + +void f4(long foo) +{ + int index = -1; + if (index < foo) index = foo; + if (index + 1 == 0) + clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} + else + clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} +} + +void f5(long foo) +{ + unsigned index = -1; + if (index < foo) index = foo; + if (index == -1) + clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} + else + clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} +} + +void f6(long foo) +{ + unsigned index = -1; + if (index < foo) index = foo; + if (index == -1) + clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} + else + clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} +} + +void f7(long foo) +{ + unsigned index = -1; + if (index < foo) index = foo; + if (index - 1 == 0) // Was not reached prior fix. + clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} + else + clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} +} + +void f8(long foo) +{ + unsigned index = -1; + if (index < foo) index = foo; + if (index + 1L == 0L) + clang_analyzer_warnIfReached(); // no-warning + else + clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} +} + +void f9(long foo) +{ + unsigned index = -1; + if (index < foo) index = foo; + if (index - 1L == 0L) // Was not reached prior fix. + clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} + else + clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} +} + +void f10(long foo) +{ + unsigned index = -1; + if (index < foo) index = foo; + if (index + 1 == 0L) + clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} + else + clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} +} + +void f11(long foo) +{ + unsigned index = -1; + if (index < foo) index = foo; + if (index + 1UL == 0L) + clang_analyzer_warnIfReached(); // no-warning + else + clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} +} + +void f12(long foo) +{ + unsigned index = -1; + if (index < foo) index = foo; + if (index - 1UL == 0L) // Was not reached prior fix. + clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} + else + clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} +} + +void f13(int foo) +{ + unsigned short index = -1; + if (index < foo) index = foo; + if (index + 1 == 0) + clang_analyzer_warnIfReached(); // no-warning + else + clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} +} + +void f14(long foo) +{ + unsigned index = -1; + if (index < foo) index = foo; + long bar = foo; + if (index + 1 == 0) + clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} + else + clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} +} + +void f15(long foo) +{ + unsigned index = -1; + if (index < foo) index = foo; + unsigned int tmp = index + 1; + if (tmp == 0) + clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} + else + clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} +} diff --git a/test/CXX/class/class.mem/p13.cpp b/test/CXX/class/class.mem/p13.cpp index 1d7b9bc81551..bc01fd4d30c5 100644 --- a/test/CXX/class/class.mem/p13.cpp +++ b/test/CXX/class/class.mem/p13.cpp @@ -58,12 +58,12 @@ struct X3a { }; // - every member of every anonymous union that is a member of class T. -struct X4 { +struct X4 { // expected-note{{previous}} union { int X; union { float Y; - unsigned X4; // expected-error{{member 'X4' has the same name as its class}} + unsigned X4; // expected-error{{redeclares 'X4'}} }; }; }; diff --git a/test/CXX/class/class.union/class.union.anon/p1.cpp b/test/CXX/class/class.union/class.union.anon/p1.cpp new file mode 100644 index 000000000000..31c9313cf53a --- /dev/null +++ b/test/CXX/class/class.union/class.union.anon/p1.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -verify %s + +struct X { + int a; // expected-note {{previous}} + void b(); // expected-note {{previous}} + struct c; // expected-note {{previous}} + typedef int d; // expected-note {{previous}} + + union { + int a; // expected-error {{member of anonymous union redeclares}} + int b; // expected-error {{member of anonymous union redeclares}} + int c; // expected-error {{member of anonymous union redeclares}} + int d; // expected-error {{member of anonymous union redeclares}} + int e; // expected-note {{previous}} + int f; // expected-note {{previous}} + int g; // expected-note {{previous}} + int h; // expected-note {{previous}} + }; + + int e; // expected-error {{duplicate member}} + void f(); // expected-error {{redefinition}} + struct g; // expected-error {{redefinition}} + typedef int h; // expected-error {{redefinition}} +}; diff --git a/test/CXX/class/class.union/class.union.anon/p4.cpp b/test/CXX/class/class.union/class.union.anon/p4.cpp new file mode 100644 index 000000000000..cc54ba406619 --- /dev/null +++ b/test/CXX/class/class.union/class.union.anon/p4.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +union U { + int x = 0; // expected-note {{previous initialization is here}} + union {}; + union { + int z; + int y = 1; // expected-error {{initializing multiple members of union}} + }; +}; diff --git a/test/CXX/class/class.union/p8.cpp b/test/CXX/class/class.union/p8.cpp deleted file mode 100644 index cc54ba406619..000000000000 --- a/test/CXX/class/class.union/p8.cpp +++ /dev/null @@ -1,10 +0,0 @@ -// RUN: %clang_cc1 -std=c++11 -verify %s - -union U { - int x = 0; // expected-note {{previous initialization is here}} - union {}; - union { - int z; - int y = 1; // expected-error {{initializing multiple members of union}} - }; -}; diff --git a/test/CXX/temp/temp.res/temp.local/p6.cpp b/test/CXX/temp/temp.res/temp.local/p6.cpp index 06eb1bef7fea..843b45543fcf 100644 --- a/test/CXX/temp/temp.res/temp.local/p6.cpp +++ b/test/CXX/temp/temp.res/temp.local/p6.cpp @@ -5,7 +5,7 @@ namespace N {} template struct X {}; // expected-error {{declaration of 'T' shadows template parameter}} -template struct Y { // expected-note 16{{declared here}} +template struct Y { // expected-note 17{{declared here}} template struct A {}; // expected-error {{declaration of 'T' shadows template parameter}} struct B { @@ -56,9 +56,74 @@ template struct Y { // expected-note 16{{declared here}} namespace T = N; // expected-error {{declaration of 'T' shadows template parameter}} } + // FIXME: These diagnostics are poorly worded. Lookup for the elaborated type + // specifier finds the template parameter in this case, which is ill-formed + // because it's not a struct. + void f() { + struct T *p; // expected-error {{declaration of 'T' shadows template parameter}} + } friend struct T; // expected-error {{declaration of 'T' shadows template parameter}} }; +template struct Z { // expected-note 15{{declared here}} + template struct A {}; // expected-error {{declaration of 'T' shadows template parameter}} + + struct B { + template struct T {}; // FIXME: desired-error {{declaration of 'T' shadows template parameter}} + }; + struct C { + template void T(); // expected-error {{declaration of 'T' shadows template parameter}} + }; + struct D { + struct T {}; // expected-error {{declaration of 'T' shadows template parameter}} + }; + struct E { + typedef int T; // expected-error {{declaration of 'T' shadows template parameter}} + }; + struct F { + using T = int; // expected-error {{declaration of 'T' shadows template parameter}} + }; + struct G { + int T; // expected-error {{declaration of 'T' shadows template parameter}} + }; + struct H { + static int T; // expected-error {{declaration of 'T' shadows template parameter}} + }; + struct I { + void T(); // expected-error {{declaration of 'T' shadows template parameter}} + }; + struct J { + enum T { e }; // expected-error {{declaration of 'T' shadows template parameter}} + }; + struct K { + enum E { T }; // expected-error {{declaration of 'T' shadows template parameter}} + }; + + void a() { + extern int T; // expected-error {{declaration of 'T' shadows template parameter}} + } + void b() { + int T; // expected-error {{declaration of 'T' shadows template parameter}} + } + void c() { + try {} + catch (int T) {} // expected-error {{declaration of 'T' shadows template parameter}} + } + void d() { + void T(); // expected-error {{declaration of 'T' shadows template parameter}} + } + void e() { + namespace T = N; // expected-error {{declaration of 'T' shadows template parameter}} + } + + // These cases are valid when 'T' is a non-type template parameter, as T + // names an injected struct ::T, which doesn't shadow the template parameter. + void f() { + struct T *p; + } + friend struct T; +}; + template // expected-note {{declared here}} void f(int T) {} // expected-error {{declaration of 'T' shadows template parameter}} diff --git a/test/CodeGen/builtins-ppc-vsx.c b/test/CodeGen/builtins-ppc-vsx.c index 9a40d3041db1..15f98b57a513 100644 --- a/test/CodeGen/builtins-ppc-vsx.c +++ b/test/CodeGen/builtins-ppc-vsx.c @@ -845,4 +845,51 @@ void test1() { // CHECK: xor <2 x i64> // CHECK-LE: xor <2 x i64> + res_vsll = vec_cts(vd, 0); +// CHECK: fmul <2 x double> +// CHECK: fptosi <2 x double> %{{.*}} to <2 x i64> +// CHECK-LE: fmul <2 x double> +// CHECK-LE: fptosi <2 x double> %{{.*}} to <2 x i64> + + res_vsll = vec_cts(vd, 31); +// CHECK: fmul <2 x double> +// CHECK: fptosi <2 x double> %{{.*}} to <2 x i64> +// CHECK-LE: fmul <2 x double> +// CHECK-LE: fptosi <2 x double> %{{.*}} to <2 x i64> + + res_vsll = vec_ctu(vd, 0); +// CHECK: fmul <2 x double> +// CHECK: fptoui <2 x double> %{{.*}} to <2 x i64> +// CHECK-LE: fmul <2 x double> +// CHECK-LE: fptoui <2 x double> %{{.*}} to <2 x i64> + + res_vsll = vec_ctu(vd, 31); +// CHECK: fmul <2 x double> +// CHECK: fptoui <2 x double> %{{.*}} to <2 x i64> +// CHECK-LE: fmul <2 x double> +// CHECK-LE: fptoui <2 x double> %{{.*}} to <2 x i64> + + res_vd = vec_ctf(vsll, 0); +// CHECK: sitofp <2 x i64> %{{.*}} to <2 x double> +// CHECK: fmul <2 x double> +// CHECK-LE: sitofp <2 x i64> %{{.*}} to <2 x double> +// CHECK-LE: fmul <2 x double> + + res_vd = vec_ctf(vsll, 31); +// CHECK: sitofp <2 x i64> %{{.*}} to <2 x double> +// CHECK: fmul <2 x double> +// CHECK-LE: sitofp <2 x i64> %{{.*}} to <2 x double> +// CHECK-LE: fmul <2 x double> + + res_vd = vec_ctf(vull, 0); +// CHECK: uitofp <2 x i64> %{{.*}} to <2 x double> +// CHECK: fmul <2 x double> +// CHECK-LE: uitofp <2 x i64> %{{.*}} to <2 x double> +// CHECK-LE: fmul <2 x double> + + res_vd = vec_ctf(vull, 31); +// CHECK: uitofp <2 x i64> %{{.*}} to <2 x double> +// CHECK: fmul <2 x double> +// CHECK-LE: uitofp <2 x i64> %{{.*}} to <2 x double> +// CHECK-LE: fmul <2 x double> } diff --git a/test/CodeGen/target-data.c b/test/CodeGen/target-data.c index 08265f9da365..2ed7f0916fce 100644 --- a/test/CodeGen/target-data.c +++ b/test/CodeGen/target-data.c @@ -80,11 +80,11 @@ // RUN: %clang_cc1 -triple wasm32-unknown-unknown -o - -emit-llvm %s | \ // RUN: FileCheck %s -check-prefix=WEBASSEMBLY32 -// WEBASSEMBLY32: target datalayout = "e-p:32:32-i64:64-n32:64-S128" +// WEBASSEMBLY32: target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" // RUN: %clang_cc1 -triple wasm64-unknown-unknown -o - -emit-llvm %s | \ // RUN: FileCheck %s -check-prefix=WEBASSEMBLY64 -// WEBASSEMBLY64: target datalayout = "e-p:64:64-i64:64-n32:64-S128" +// WEBASSEMBLY64: target datalayout = "e-m:e-p:64:64-i64:64-n32:64-S128" // RUN: %clang_cc1 -triple powerpc-unknown -o - -emit-llvm %s | \ // RUN: FileCheck %s -check-prefix=PPC diff --git a/test/CodeGenCXX/builtins-systemz-zvector.cpp b/test/CodeGenCXX/builtins-systemz-zvector.cpp new file mode 100644 index 000000000000..aedb30ffbb4c --- /dev/null +++ b/test/CodeGenCXX/builtins-systemz-zvector.cpp @@ -0,0 +1,50 @@ +// REQUIRES: systemz-registered-target +// RUN: %clang_cc1 -target-cpu z13 -triple s390x-linux-gnu \ +// RUN: -fzvector -fno-lax-vector-conversions -std=c++11 \ +// RUN: -Wall -Wno-unused -Werror -emit-llvm %s -o - | FileCheck %s + +bool gb; + +// There was an issue where we weren't properly converting constexprs to +// vectors with elements of the appropriate width. (e.g. +// (vector signed short)0 would be lowered as [4 x i32] in some cases) + +// CHECK-LABEL: @_Z8testIntsDv4_i +void testInts(vector int VI) { + constexpr vector int CI1 = (vector int)0LL; + // CHECK: icmp + gb = (VI == CI1)[0]; + + // Likewise for float inits. + constexpr vector int CI2 = (vector int)char(0); + // CHECK: icmp + gb = (VI == CI2)[0]; + + constexpr vector int CF1 = (vector int)0.0; + // CHECK: icmp + gb = (VI == CF1)[0]; + + constexpr vector int CF2 = (vector int)0.0f; + // CHECK: icmp + gb = (VI == CF2)[0]; +} + +// CHECK-LABEL: @_Z10testFloatsDv2_d +void testFloats(vector double VD) { + constexpr vector double CI1 = (vector double)0LL; + // CHECK: fcmp + gb = (VD == CI1)[0]; + + // Likewise for float inits. + constexpr vector double CI2 = (vector double)char(0); + // CHECK: fcmp + gb = (VD == CI2)[0]; + + constexpr vector double CF1 = (vector double)0.0; + // CHECK: fcmp + gb = (VD == CF1)[0]; + + constexpr vector double CF2 = (vector double)0.0f; + // CHECK: fcmp + gb = (VD == CF2)[0]; +} diff --git a/test/CodeGenCXX/mangle-ms.cpp b/test/CodeGenCXX/mangle-ms.cpp index c2a311423a9d..c82fca49f613 100644 --- a/test/CodeGenCXX/mangle-ms.cpp +++ b/test/CodeGenCXX/mangle-ms.cpp @@ -454,3 +454,28 @@ namespace Complex { // CHECK-DAG: define void @"\01?f@Complex@@YAXU?$_Complex@H@__clang@@@Z"( void f(_Complex int) {} } + +namespace PR26029 { +template +struct L { + L() {} +}; +template +class H; +struct M : L > {}; + +template +struct H {}; + +template +void m_fn3() { + (H()); + M(); +} + +void runOnFunction() { + L > b; + m_fn3(); +} +// CHECK-DAG: call {{.*}} @"\01??0?$L@V?$H@PAH@PR26029@@@PR26029@@QAE@XZ" +} diff --git a/test/CodeGenCXX/pass-object-size.cpp b/test/CodeGenCXX/pass-object-size.cpp index 254669b97627..2c7f9742a8e6 100644 --- a/test/CodeGenCXX/pass-object-size.cpp +++ b/test/CodeGenCXX/pass-object-size.cpp @@ -25,3 +25,21 @@ void Lambdas(char *ptr) { // CHECK-DAG: define internal i64 @"_ZZN7lambdas7LambdasEPcENK3$_1clEPvU17pass_object_size0" // CHECK-NOT: call i64 @llvm.objectsize } + +// This is here instead of in Sema/ because we need to check to make sure the +// proper function is called. If it's not, we'll end up with assertion errors. +namespace addrof { +void OvlFoo(void *const __attribute__((pass_object_size(0)))) {} +void OvlFoo(int *const) {} + +// CHECK: define void @_ZN6addrof4TestEv +void Test() { + // Treating parens-only calls as though they were direct is consistent with + // how we handle other implicitly unaddressable functions (e.g. builtins). + // CHECK: call void @_ZN6addrof6OvlFooEPvU17pass_object_size0 + (OvlFoo)(nullptr); + + // CHECK: call void @_ZN6addrof6OvlFooEPi + (&OvlFoo)(nullptr); +} +} diff --git a/test/CodeGenCXX/vector-splat-conversion.cpp b/test/CodeGenCXX/vector-splat-conversion.cpp index 410df3dd0cef..805f9f5bab15 100644 --- a/test/CodeGenCXX/vector-splat-conversion.cpp +++ b/test/CodeGenCXX/vector-splat-conversion.cpp @@ -1,19 +1,51 @@ // RUN: %clang_cc1 %s -triple arm64-apple-ios8.1.0 -std=c++11 -emit-llvm -o - | FileCheck %s -// rdar://20000762 typedef __attribute__((__ext_vector_type__(8))) float vector_float8; typedef vector_float8 float8; -void MandelbrotPolyCalcSIMD8() -{ - constexpr float8 v4 = 4.0; // value to compare against abs(z)^2, to see if bounded - float8 vABS; - auto vLT = vABS < v4; +// rdar://20000762 +// CHECK-LABEL: define void @_Z23MandelbrotPolyCalcSIMD8v +void MandelbrotPolyCalcSIMD8() { + constexpr float8 v4 = 4.0; // value to compare against abs(z)^2, to see if bounded + float8 vABS; + auto vLT = vABS < v4; + // CHECK: store <8 x float> + // CHECK: [[ZERO:%.*]] = load <8 x float>, <8 x float>* [[VARBS:%.*]] + // CHECK: [[CMP:%.*]] = fcmp olt <8 x float> [[ZERO]] + // CHECK: [[SEXT:%.*]] = sext <8 x i1> [[CMP]] to <8 x i32> + // CHECK: store <8 x i32> [[SEXT]], <8 x i32>* [[VLT:%.*]] } -// CHECK: store <8 x float> -// CHECK: [[ZERO:%.*]] = load <8 x float>, <8 x float>* [[VARBS:%.*]] -// CHECK: [[CMP:%.*]] = fcmp olt <8 x float> [[ZERO]] -// CHECK: [[SEXT:%.*]] = sext <8 x i1> [[CMP]] to <8 x i32> -// CHECK: store <8 x i32> [[SEXT]], <8 x i32>* [[VLT:%.*]] +typedef __attribute__((__ext_vector_type__(4))) int int4; +typedef __attribute__((__ext_vector_type__(4))) float float4; +typedef __attribute__((__ext_vector_type__(4))) __int128 bigint4; + +// CHECK-LABEL: define void @_Z14BoolConversionv +void BoolConversion() { + // CHECK: store <4 x i32> + int4 intsT = (int4)true; + // CHECK: store <4 x i32> zeroinitializer + int4 intsF = (int4)false; + // CHECK: store <4 x float> + float4 floatsT = (float4)true; + // CHECK: store <4 x float> zeroinitializer + float4 floatsF = (float4)false; + // CHECK: store <4 x i128> + bigint4 bigintsT = (bigint4)true; + // CHECK: store <4 x i128> zeroinitializer + bigint4 bigintsF = (bigint4)false; + + // CHECK: store <4 x i32> + constexpr int4 cIntsT = (int4)true; + // CHECK: store <4 x i32> zeroinitializer + constexpr int4 cIntsF = (int4)false; + // CHECK: store <4 x float> + constexpr float4 cFloatsT = (float4)true; + // CHECK: store <4 x float> zeroinitializer + constexpr float4 cFloatsF = (float4)false; + // CHECK: store <4 x i128> + constexpr bigint4 cBigintsT = (bigint4)true; + // CHECK: store <4 x i128> zeroinitializer + constexpr bigint4 cBigintsF = (bigint4)false; +} diff --git a/test/CodeGenOpenCL/bool_cast.cl b/test/CodeGenOpenCL/bool_cast.cl index d63431b1b7ca..8c86b06577d6 100644 --- a/test/CodeGenOpenCL/bool_cast.cl +++ b/test/CodeGenOpenCL/bool_cast.cl @@ -2,7 +2,9 @@ typedef unsigned char uchar4 __attribute((ext_vector_type(4))); typedef unsigned int int4 __attribute((ext_vector_type(4))); +typedef float float4 __attribute((ext_vector_type(4))); +// CHECK-LABEL: define void @ker() void kernel ker() { bool t = true; int4 vec4 = (int4)t; @@ -24,4 +26,8 @@ void kernel ker() { unsigned char c; c = (unsigned char)true; // CHECK: store i8 1, i8* %c, align 1 + + float4 vf; + vf = (float4)true; +// CHECK: store <4 x float> } diff --git a/test/CodeGenOpenCL/pipe_types.cl b/test/CodeGenOpenCL/pipe_types.cl new file mode 100644 index 000000000000..547071cf85a3 --- /dev/null +++ b/test/CodeGenOpenCL/pipe_types.cl @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -emit-llvm -O0 -cl-std=CL2.0 -o - %s | FileCheck %s + +// CHECK: %opencl.pipe_t = type opaque +typedef unsigned char __attribute__((ext_vector_type(3))) uchar3; +typedef int __attribute__((ext_vector_type(4))) int4; + +void test1(read_only pipe int p) { +// CHECK: define void @test1(%opencl.pipe_t* %p) + reserve_id_t rid; +// CHECK: %rid = alloca %opencl.reserve_id_t +} + +void test2(write_only pipe float p) { +// CHECK: define void @test2(%opencl.pipe_t* %p) +} + +void test3(read_only pipe const int p) { +// CHECK: define void @test3(%opencl.pipe_t* %p) +} + +void test4(read_only pipe uchar3 p) { +// CHECK: define void @test4(%opencl.pipe_t* %p) +} + +void test5(read_only pipe int4 p) { +// CHECK: define void @test5(%opencl.pipe_t* %p) +} diff --git a/test/Driver/amdgpu-toolchain.c b/test/Driver/amdgpu-toolchain.c index 41cef7f4c323..c84a154c7c18 100644 --- a/test/Driver/amdgpu-toolchain.c +++ b/test/Driver/amdgpu-toolchain.c @@ -1,3 +1,3 @@ // RUN: %clang -### -target amdgcn--amdhsa -x assembler -mcpu=kaveri %s 2>&1 | FileCheck -check-prefix=AS_LINK %s // AS_LINK: clang{{.*}} "-cc1as" -// AS_LINK: lld{{.*}} "-flavor" "old-gnu" "-target" "amdgcn--amdhsa" +// AS_LINK: ld.lld{{.*}} diff --git a/test/Driver/appletvos-version-min.c b/test/Driver/appletvos-version-min.c index 9ff8297fe9eb..7cbb2001a3ec 100644 --- a/test/Driver/appletvos-version-min.c +++ b/test/Driver/appletvos-version-min.c @@ -2,6 +2,7 @@ // REQUIRES: aarch64-registered-target // RUN: %clang -target i386-apple-darwin10 -mappletvsimulator-version-min=9.0 -arch x86_64 -S -o - %s | FileCheck %s // RUN: %clang -target armv7s-apple-darwin10 -mappletvos-version-min=9.0 -arch arm64 -S -o - %s | FileCheck %s +// RUN: env TVOS_DEPLOYMENT_TARGET=9.0 %clang -isysroot SDKs/MacOSX10.9.sdk -target i386-apple-darwin10 -arch x86_64 -S -o - %s | FileCheck %s int main() { return 0; } // CHECK: .tvos_version_min 9, 0 diff --git a/test/Driver/arm-xscale.c b/test/Driver/arm-xscale.c new file mode 100644 index 000000000000..9b00b832095d --- /dev/null +++ b/test/Driver/arm-xscale.c @@ -0,0 +1,3 @@ +// RUN: %clang -target arm-freebsd -mcpu=xscale -### -c %s 2>&1 | FileCheck %s +// CHECK-NOT: error: the clang compiler does not support '-mcpu=xscale' +// CHECK: "-cc1"{{.*}} "-target-cpu" "xscale"{{.*}} diff --git a/test/Driver/cl-options.c b/test/Driver/cl-options.c index c23aefea146d..c5985a9c2b24 100644 --- a/test/Driver/cl-options.c +++ b/test/Driver/cl-options.c @@ -14,9 +14,14 @@ // C_P: "-E" // C_P: "-C" -// RUN: %clang_cl /Dfoo=bar -### -- %s 2>&1 | FileCheck -check-prefix=D %s -// RUN: %clang_cl /D foo=bar -### -- %s 2>&1 | FileCheck -check-prefix=D %s +// RUN: %clang_cl /Dfoo=bar /D bar=baz /DMYDEF#value /DMYDEF2=foo#bar /DMYDEF3#a=b /DMYDEF4# \ +// RUN: -### -- %s 2>&1 | FileCheck -check-prefix=D %s // D: "-D" "foo=bar" +// D: "-D" "bar=baz" +// D: "-D" "MYDEF=value" +// D: "-D" "MYDEF2=foo#bar" +// D: "-D" "MYDEF3=a=b" +// D: "-D" "MYDEF4=" // RUN: %clang_cl /E -### -- %s 2>&1 | FileCheck -check-prefix=E %s // E: "-E" diff --git a/test/Driver/cuda-bad-arch.cu b/test/Driver/cuda-bad-arch.cu new file mode 100644 index 000000000000..f92bdcebd0d5 --- /dev/null +++ b/test/Driver/cuda-bad-arch.cu @@ -0,0 +1,22 @@ +// Checks errors generated by passing a bad value for --cuda-gpu-arch. +// REQUIRES: clang-driver +// REQUIRES: x86-registered-target +// REQUIRES: nvptx-registered-target + +// RUN: %clang -### -target x86_64-linux-gnu --cuda-gpu-arch=compute_20 -c %s 2>&1 \ +// RUN: | FileCheck -check-prefix BAD %s +// RUN: %clang -### -target x86_64-linux-gnu --cuda-gpu-arch=sm20 -c %s 2>&1 \ +// RUN: | FileCheck -check-prefix BAD %s +// RUN: %clang -### -target x86_64-linux-gnu --cuda-gpu-arch=sm_19 -c %s 2>&1 \ +// RUN: | FileCheck -check-prefix BAD %s + +// BAD: error: Unsupported CUDA gpu architecture + +// RUN: %clang -### -target x86_64-linux-gnu --cuda-gpu-arch=sm_20 -c %s 2>&1 \ +// RUN: | FileCheck -check-prefix OK %s +// RUN: %clang -### -target x86_64-linux-gnu --cuda-gpu-arch=sm_52 -c %s 2>&1 \ +// RUN: | FileCheck -check-prefix OK %s +// RUN: %clang -### -target x86_64-linux-gnu -c %s 2>&1 \ +// RUN: | FileCheck -check-prefix OK %s + +// OK-NOT: error: Unsupported CUDA gpu architecture diff --git a/test/Driver/cuda-options.cu b/test/Driver/cuda-options.cu index 21625259d3ef..bf71633a4cf9 100644 --- a/test/Driver/cuda-options.cu +++ b/test/Driver/cuda-options.cu @@ -3,193 +3,140 @@ // REQUIRES: x86-registered-target // REQUIRES: nvptx-registered-target -// Simple compilation case: +// Simple compilation case. Compile device-side to PTX assembly and make sure +// we use it on the host side. // RUN: %clang -### -target x86_64-linux-gnu -c %s 2>&1 \ -// Compile device-side to PTX assembly and make sure we use it on the host side. -// RUN: | FileCheck -check-prefix CUDA-D1 -check-prefix CUDA-D1NS\ -// Then compile host side and incorporate device code. -// RUN: -check-prefix CUDA-H -check-prefix CUDA-H-I1 \ -// Make sure we don't link anything. -// RUN: -check-prefix CUDA-NL %s - -// Typical compilation + link case: +// RUN: | FileCheck -check-prefix DEVICE -check-prefix DEVICE-NOSAVE \ +// RUN: -check-prefix HOST -check-prefix INCLUDES-DEVICE \ +// RUN: -check-prefix NOLINK %s + +// Typical compilation + link case. // RUN: %clang -### -target x86_64-linux-gnu %s 2>&1 \ -// Compile device-side to PTX assembly and make sure we use it on the host side -// RUN: | FileCheck -check-prefix CUDA-D1 -check-prefix CUDA-D1NS\ -// Then compile host side and incorporate device code. -// RUN: -check-prefix CUDA-H -check-prefix CUDA-H-I1 \ -// Then link things. -// RUN: -check-prefix CUDA-L %s - -// Verify that --cuda-host-only disables device-side compilation and linking +// RUN: | FileCheck -check-prefix DEVICE -check-prefix DEVICE-NOSAVE \ +// RUN: -check-prefix HOST -check-prefix INCLUDES-DEVICE \ +// RUN: -check-prefix LINK %s + +// Verify that --cuda-host-only disables device-side compilation, but doesn't +// disable host-side compilation/linking. // RUN: %clang -### -target x86_64-linux-gnu --cuda-host-only %s 2>&1 \ -// Make sure we didn't run device-side compilation. -// RUN: | FileCheck -check-prefix CUDA-ND \ -// Then compile host side and make sure we don't attempt to incorporate GPU code. -// RUN: -check-prefix CUDA-H -check-prefix CUDA-H-NI \ -// Linking is allowed to happen, even if we're missing GPU code. -// RUN: -check-prefix CUDA-L %s - -// Same test as above, but with preceeding --cuda-device-only to make -// sure only last option has effect. +// RUN: | FileCheck -check-prefix NODEVICE -check-prefix HOST \ +// RUN: -check-prefix NOINCLUDES-DEVICE -check-prefix LINK %s + +// Same test as above, but with preceeding --cuda-device-only to make sure only +// the last option has an effect. // RUN: %clang -### -target x86_64-linux-gnu --cuda-device-only --cuda-host-only %s 2>&1 \ -// Make sure we didn't run device-side compilation. -// RUN: | FileCheck -check-prefix CUDA-ND \ -// Then compile host side and make sure we don't attempt to incorporate GPU code. -// RUN: -check-prefix CUDA-H -check-prefix CUDA-H-NI \ -// Linking is allowed to happen, even if we're missing GPU code. -// RUN: -check-prefix CUDA-L %s - -// Verify that --cuda-device-only disables host-side compilation and linking +// RUN: | FileCheck -check-prefix NODEVICE -check-prefix HOST \ +// RUN: -check-prefix NOINCLUDES-DEVICE -check-prefix LINK %s + +// Verify that --cuda-device-only disables host-side compilation and linking. // RUN: %clang -### -target x86_64-linux-gnu --cuda-device-only %s 2>&1 \ -// Compile device-side to PTX assembly -// RUN: | FileCheck -check-prefix CUDA-D1 -check-prefix CUDA-D1NS\ -// Make sure there are no host cmpilation or linking. -// RUN: -check-prefix CUDA-NH -check-prefix CUDA-NL %s +// RUN: | FileCheck -check-prefix DEVICE -check-prefix DEVICE-NOSAVE \ +// RUN: -check-prefix NOHOST -check-prefix NOLINK %s -// Same test as above, but with preceeding --cuda-host-only to make -// sure only last option has effect. +// Same test as above, but with preceeding --cuda-host-only to make sure only +// the last option has an effect. // RUN: %clang -### -target x86_64-linux-gnu --cuda-host-only --cuda-device-only %s 2>&1 \ -// Compile device-side to PTX assembly -// RUN: | FileCheck -check-prefix CUDA-D1 -check-prefix CUDA-D1NS\ -// Make sure there are no host cmpilation or linking. -// RUN: -check-prefix CUDA-NH -check-prefix CUDA-NL %s +// RUN: | FileCheck -check-prefix DEVICE -check-prefix DEVICE-NOSAVE \ +// RUN: -check-prefix NOHOST -check-prefix NOLINK %s -// Verify that with -S we compile host and device sides to assembly -// and incorporate device code on the host side. +// Verify that with -S we compile host and device sides to assembly and +// incorporate device code into the host side. // RUN: %clang -### -target x86_64-linux-gnu -S -c %s 2>&1 \ -// Compile device-side to PTX assembly -// RUN: | FileCheck -check-prefix CUDA-D1 -check-prefix CUDA-D1NS\ -// Then compile host side and incorporate GPU code. -// RUN: -check-prefix CUDA-H -check-prefix CUDA-H-I1 \ -// Make sure we don't link anything. -// RUN: -check-prefix CUDA-NL %s - -// Verify that --cuda-gpu-arch option passes correct GPU -// archtecture info to device compilation. +// RUN: | FileCheck -check-prefix DEVICE -check-prefix DEVICE-NOSAVE \ +// RUN: -check-prefix HOST -check-prefix INCLUDES-DEVICE \ +// RUN: -check-prefix NOLINK %s + +// Verify that --cuda-gpu-arch option passes the correct GPU archtecture to +// device compilation. // RUN: %clang -### -target x86_64-linux-gnu --cuda-gpu-arch=sm_35 -c %s 2>&1 \ -// Compile device-side to PTX assembly. -// RUN: | FileCheck -check-prefix CUDA-D1 -check-prefix CUDA-D1NS \ -// RUN: -check-prefix CUDA-D1-SM35 \ -// Then compile host side and incorporate GPU code. -// RUN: -check-prefix CUDA-H -check-prefix CUDA-H-I1 \ -// Make sure we don't link anything. -// RUN: -check-prefix CUDA-NL %s - -// Verify that there is device-side compilation per --cuda-gpu-arch args +// RUN: | FileCheck -check-prefix DEVICE -check-prefix DEVICE-NOSAVE \ +// RUN: -check-prefix DEVICE-SM35 -check-prefix HOST \ +// RUN: -check-prefix INCLUDES-DEVICE -check-prefix NOLINK %s + +// Verify that there is one device-side compilation per --cuda-gpu-arch args // and that all results are included on the host side. // RUN: %clang -### -target x86_64-linux-gnu \ -// RUN: --cuda-gpu-arch=sm_35 --cuda-gpu-arch=sm_30 -c %s 2>&1 \ -// Compile both device-sides to PTX assembly -// RUN: | FileCheck \ -// RUN: -check-prefix CUDA-D1 -check-prefix CUDA-D1NS -check-prefix CUDA-D1-SM35 \ -// RUN: -check-prefix CUDA-D2 -check-prefix CUDA-D2-SM30 \ -// Then compile host side and incorporate both device-side outputs -// RUN: -check-prefix CUDA-H -check-prefix CUDA-HNS \ -// RUN: -check-prefix CUDA-H-I1 -check-prefix CUDA-H-I2 \ -// Make sure we don't link anything. -// RUN: -check-prefix CUDA-NL %s - -// Verify that device-side results are passed to correct tool when -// -save-temps is used +// RUN: --cuda-gpu-arch=sm_35 --cuda-gpu-arch=sm_30 -c %s 2>&1 \ +// RUN: | FileCheck -check-prefix DEVICE -check-prefix DEVICE-NOSAVE \ +// RUN: -check-prefix DEVICE2 -check-prefix DEVICE-SM35 \ +// RUN: -check-prefix DEVICE2-SM30 -check-prefix HOST \ +// RUN: -check-prefix HOST-NOSAVE -check-prefix INCLUDES-DEVICE \ +// RUN: -check-prefix INCLUDES-DEVICE2 -check-prefix NOLINK %s + +// Verify that device-side results are passed to the correct tool when +// -save-temps is used. // RUN: %clang -### -target x86_64-linux-gnu -save-temps -c %s 2>&1 \ -// Compile device-side to PTX assembly and make sure we use it on the host side. -// RUN: | FileCheck -check-prefix CUDA-D1 -check-prefix CUDA-D1S \ -// Then compile host side and incorporate device code. -// RUN: -check-prefix CUDA-H -check-prefix CUDA-HS -check-prefix CUDA-HS-I1 \ -// Make sure we don't link anything. -// RUN: -check-prefix CUDA-NL %s - -// Verify that device-side results are passed to correct tool when -// -fno-integrated-as is used +// RUN: | FileCheck -check-prefix DEVICE -check-prefix DEVICE-SAVE \ +// RUN: -check-prefix HOST -check-prefix HOST-SAVE -check-prefix NOLINK %s + +// Verify that device-side results are passed to the correct tool when +// -fno-integrated-as is used. // RUN: %clang -### -target x86_64-linux-gnu -fno-integrated-as -c %s 2>&1 \ -// Compile device-side to PTX assembly and make sure we use it on the host side. -// RUN: | FileCheck -check-prefix CUDA-D1 -check-prefix CUDA-D1NS \ -// Then compile host side and incorporate device code. -// RUN: -check-prefix CUDA-H -check-prefix CUDA-HNS -check-prefix CUDA-HS-I1 \ -// RUN: -check-prefix CUDA-H-AS \ -// Make sure we don't link anything. -// RUN: -check-prefix CUDA-NL %s - -// --cuda-host-only should never trigger unused arg warning. -// RUN: %clang -### -target x86_64-linux-gnu --cuda-host-only -c %s 2>&1 | \ -// RUN: FileCheck -check-prefix CUDA-NO-UNUSED-CHO %s -// RUN: %clang -### -target x86_64-linux-gnu --cuda-host-only -x c -c %s 2>&1 | \ -// RUN: FileCheck -check-prefix CUDA-NO-UNUSED-CHO %s - -// --cuda-device-only should not produce warning compiling CUDA files -// RUN: %clang -### -target x86_64-linux-gnu --cuda-device-only -c %s 2>&1 | \ -// RUN: FileCheck -check-prefix CUDA-NO-UNUSED-CDO %s - -// --cuda-device-only should warn during non-CUDA compilation. -// RUN: %clang -### -target x86_64-linux-gnu --cuda-device-only -x c -c %s 2>&1 | \ -// RUN: FileCheck -check-prefix CUDA-UNUSED-CDO %s - -// Match device-side preprocessor, and compiler phases with -save-temps -// CUDA-D1S: "-cc1" "-triple" "nvptx64-nvidia-cuda" -// CUDA-D1S-SAME: "-aux-triple" "x86_64--linux-gnu" -// CUDA-D1S-SAME: "-fcuda-is-device" -// CUDA-D1S-SAME: "-x" "cuda" - -// CUDA-D1S: "-cc1" "-triple" "nvptx64-nvidia-cuda" -// CUDA-D1S-SAME: "-aux-triple" "x86_64--linux-gnu" -// CUDA-D1S-SAME: "-fcuda-is-device" -// CUDA-D1S-SAME: "-x" "cuda-cpp-output" - -// Match the job that produces PTX assembly -// CUDA-D1: "-cc1" "-triple" "nvptx64-nvidia-cuda" -// CUDA-D1NS-SAME: "-aux-triple" "x86_64--linux-gnu" -// CUDA-D1-SAME: "-fcuda-is-device" -// CUDA-D1-SM35-SAME: "-target-cpu" "sm_35" -// CUDA-D1-SAME: "-o" "[[GPUBINARY1:[^"]*]]" -// CUDA-D1NS-SAME: "-x" "cuda" -// CUDA-D1S-SAME: "-x" "ir" - -// Match another device-side compilation -// CUDA-D2: "-cc1" "-triple" "nvptx64-nvidia-cuda" -// CUDA-D2-SAME: "-aux-triple" "x86_64--linux-gnu" -// CUDA-D2-SAME: "-fcuda-is-device" -// CUDA-D2-SM30-SAME: "-target-cpu" "sm_30" -// CUDA-D2-SAME: "-o" "[[GPUBINARY2:[^"]*]]" -// CUDA-D2-SAME: "-x" "cuda" - -// Match no device-side compilation -// CUDA-ND-NOT: "-cc1" "-triple" "nvptx64-nvidia-cuda" -// CUDA-ND-SAME-NOT: "-fcuda-is-device" - -// Match host-side preprocessor job with -save-temps -// CUDA-HS: "-cc1" "-triple" "x86_64--linux-gnu" -// CUDA-HS-SAME: "-aux-triple" "nvptx64-nvidia-cuda" -// CUDA-HS-SAME-NOT: "-fcuda-is-device" -// CUDA-HS-SAME: "-x" "cuda" - -// Match host-side compilation -// CUDA-H: "-cc1" "-triple" "x86_64--linux-gnu" -// CUDA-H-SAME: "-aux-triple" "nvptx64-nvidia-cuda" -// CUDA-H-SAME-NOT: "-fcuda-is-device" -// CUDA-H-SAME: "-o" "[[HOSTOUTPUT:[^"]*]]" -// CUDA-HNS-SAME: "-x" "cuda" -// CUDA-HS-SAME: "-x" "cuda-cpp-output" -// CUDA-H-I1-SAME: "-fcuda-include-gpubinary" "[[GPUBINARY1]]" -// CUDA-H-I2-SAME: "-fcuda-include-gpubinary" "[[GPUBINARY2]]" - -// Match external assembler that uses compilation output -// CUDA-H-AS: "-o" "{{.*}}.o" "[[HOSTOUTPUT]]" +// RUN: | FileCheck -check-prefix DEVICE -check-prefix DEVICE-NOSAVE \ +// RUN: -check-prefix HOST -check-prefix HOST-NOSAVE \ +// RUN: -check-prefix HOST-AS -check-prefix NOLINK %s + +// Match device-side preprocessor and compiler phases with -save-temps. +// DEVICE-SAVE: "-cc1" "-triple" "nvptx64-nvidia-cuda" +// DEVICE-SAVE-SAME: "-aux-triple" "x86_64--linux-gnu" +// DEVICE-SAVE-SAME: "-fcuda-is-device" +// DEVICE-SAVE-SAME: "-x" "cuda" + +// DEVICE-SAVE: "-cc1" "-triple" "nvptx64-nvidia-cuda" +// DEVICE-SAVE-SAME: "-aux-triple" "x86_64--linux-gnu" +// DEVICE-SAVE-SAME: "-fcuda-is-device" +// DEVICE-SAVE-SAME: "-x" "cuda-cpp-output" + +// Match the job that produces PTX assembly. +// DEVICE: "-cc1" "-triple" "nvptx64-nvidia-cuda" +// DEVICE-NOSAVE-SAME: "-aux-triple" "x86_64--linux-gnu" +// DEVICE-SAME: "-fcuda-is-device" +// DEVICE-SM35-SAME: "-target-cpu" "sm_35" +// DEVICE-SAME: "-o" "[[GPUBINARY1:[^"]*]]" +// DEVICE-NOSAVE-SAME: "-x" "cuda" +// DEVICE-SAVE-SAME: "-x" "ir" + +// Match another device-side compilation. +// DEVICE2: "-cc1" "-triple" "nvptx64-nvidia-cuda" +// DEVICE2-SAME: "-aux-triple" "x86_64--linux-gnu" +// DEVICE2-SAME: "-fcuda-is-device" +// DEVICE2-SM30-SAME: "-target-cpu" "sm_30" +// DEVICE2-SAME: "-o" "[[GPUBINARY2:[^"]*]]" +// DEVICE2-SAME: "-x" "cuda" + +// Match no device-side compilation. +// NODEVICE-NOT: "-cc1" "-triple" "nvptx64-nvidia-cuda" +// NODEVICE-SAME-NOT: "-fcuda-is-device" + +// Match host-side preprocessor job with -save-temps. +// HOST-SAVE: "-cc1" "-triple" "x86_64--linux-gnu" +// HOST-SAVE-SAME: "-aux-triple" "nvptx64-nvidia-cuda" +// HOST-SAVE-SAME-NOT: "-fcuda-is-device" +// HOST-SAVE-SAME: "-x" "cuda" + +// Match host-side compilation. +// HOST: "-cc1" "-triple" "x86_64--linux-gnu" +// HOST-SAME: "-aux-triple" "nvptx64-nvidia-cuda" +// HOST-SAME-NOT: "-fcuda-is-device" +// HOST-SAME: "-o" "[[HOSTOUTPUT:[^"]*]]" +// HOST-NOSAVE-SAME: "-x" "cuda" +// HOST-SAVE-SAME: "-x" "cuda-cpp-output" +// INCLUDES-DEVICE-SAME: "-fcuda-include-gpubinary" "[[GPUBINARY1]]" +// INCLUDES-DEVICE2-SAME: "-fcuda-include-gpubinary" "[[GPUBINARY2]]" + +// Match external assembler that uses compilation output. +// HOST-AS: "-o" "{{.*}}.o" "[[HOSTOUTPUT]]" // Match no GPU code inclusion. -// CUDA-H-NI-NOT: "-fcuda-include-gpubinary" - -// Match no CUDA compilation -// CUDA-NH-NOT: "-cc1" "-triple" -// CUDA-NH-SAME-NOT: "-x" "cuda" +// NOINCLUDES-DEVICE-NOT: "-fcuda-include-gpubinary" -// Match linker -// CUDA-L: "{{.*}}{{ld|link}}{{(.exe)?}}" -// CUDA-L-SAME: "[[HOSTOUTPUT]]" +// Match no host compilation. +// NOHOST-NOT: "-cc1" "-triple" +// NOHOST-SAME-NOT: "-x" "cuda" -// Match no linker -// CUDA-NL-NOT: "{{.*}}{{ld|link}}{{(.exe)?}}" +// Match linker. +// LINK: "{{.*}}{{ld|link}}{{(.exe)?}}" +// LINK-SAME: "[[HOSTOUTPUT]]" -// CUDA-NO-UNUSED-CHO-NOT: warning: argument unused during compilation: '--cuda-host-only' -// CUDA-UNUSED-CDO: warning: argument unused during compilation: '--cuda-device-only' -// CUDA-NO-UNUSED-CDO-NOT: warning: argument unused during compilation: '--cuda-device-only' +// Match no linker. +// NOLINK-NOT: "{{.*}}{{ld|link}}{{(.exe)?}}" diff --git a/test/Driver/cuda-unused-arg-warning.cu b/test/Driver/cuda-unused-arg-warning.cu new file mode 100644 index 000000000000..e8daad6cdaf6 --- /dev/null +++ b/test/Driver/cuda-unused-arg-warning.cu @@ -0,0 +1,23 @@ +// Tests that we trigger unused-arg warnings on CUDA flags appropriately. + +// REQUIRES: clang-driver +// REQUIRES: x86-registered-target +// REQUIRES: nvptx-registered-target + +// --cuda-host-only should never trigger unused arg warning. +// RUN: %clang -### -target x86_64-linux-gnu --cuda-host-only -c %s 2>&1 | \ +// RUN: FileCheck %s +// RUN: %clang -### -target x86_64-linux-gnu --cuda-host-only -x c -c %s 2>&1 | \ +// RUN: FileCheck %s + +// --cuda-device-only should warn during non-CUDA compilation. +// RUN: %clang -### -target x86_64-linux-gnu --cuda-device-only -x c -c %s 2>&1 | \ +// RUN: FileCheck -check-prefix UNUSED-WARNING %s + +// --cuda-device-only should not produce warning compiling CUDA files +// RUN: %clang -### -target x86_64-linux-gnu --cuda-device-only -c %s 2>&1 | \ +// RUN: FileCheck -check-prefix NO-UNUSED-WARNING %s + +// CHECK-NOT: warning: argument unused during compilation: '--cuda-host-only' +// UNUSED-WARNING: warning: argument unused during compilation: '--cuda-device-only' +// NO-UNUSED-WARNING-NOT: warning: argument unused during compilation: '--cuda-device-only' diff --git a/test/Driver/debug-options.c b/test/Driver/debug-options.c index 72d0136a8c40..0ccacd0fc6c7 100644 --- a/test/Driver/debug-options.c +++ b/test/Driver/debug-options.c @@ -32,7 +32,7 @@ // RUN: | FileCheck -check-prefix=G_DARWIN %s // RUN: %clang -### -c -g %s -target x86_64-pc-freebsd10.0 2>&1 \ -// RUN: | FileCheck -check-prefix=G_LLDB %s +// RUN: | FileCheck -check-prefix=G_GDB %s // On the PS4, -g defaults to -gno-column-info, and we always generate the // arange section. diff --git a/test/Driver/fortran.f95 b/test/Driver/fortran.f95 index 982f4eb5e6df..47c6e7b50c95 100644 --- a/test/Driver/fortran.f95 +++ b/test/Driver/fortran.f95 @@ -13,3 +13,9 @@ // CHECK-ASM: "-S" // CHECK-ASM: "-x" "f95" // CHECK-ASM-NOT: cc1 + +// RUN: %clang -Wall -target x86_64-unknown-linux-gnu -integrated-as %s -o %t -### 2>&1 | FileCheck --check-prefix=CHECK-WARN %s +// CHECK-WARN: gcc +// CHECK-WARN-NOT: "-Wall" +// CHECK-WARN: ld +// CHECK-WARN-NOT: "-Wall" diff --git a/test/Driver/gcc_forward.c b/test/Driver/gcc_forward.c index 4892bd92ac69..d28e432b1e17 100644 --- a/test/Driver/gcc_forward.c +++ b/test/Driver/gcc_forward.c @@ -5,15 +5,16 @@ // RUN: %s \ // RUN: -Wall -Wdocumentation \ // RUN: -Xclang foo-bar \ -// RUN: -march=x86_64 \ +// RUN: -march=x86-64 \ // RUN: -mlinker-version=10 -### 2> %t // RUN: FileCheck < %t %s // -// clang-cc1 +// clang -cc1 +// CHECK: clang // CHECK: "-Wall" "-Wdocumentation" // CHECK: "-o" "{{[^"]+}}.o" // -// gcc-ld +// gcc as ld. // CHECK: gcc{{[^"]*}}" // CHECK-NOT: "-mlinker-version=10" // CHECK-NOT: "-Xclang" @@ -27,3 +28,9 @@ // CHECK-NOT: "-Wall" // CHECK-NOT: "-Wdocumentation" // CHECK: "-o" "a.out" + +// Check that we're not forwarding -g options to the assembler +// RUN: %clang -g -target x86_64-unknown-linux-gnu -no-integrated-as -c %s -### 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-ASM %s +// CHECK-ASM: as +// CHECK-ASM-NOT: "-g" diff --git a/test/Driver/pic.c b/test/Driver/pic.c index 06b4204e60da..aeb2ee33114c 100644 --- a/test/Driver/pic.c +++ b/test/Driver/pic.c @@ -218,6 +218,8 @@ // RUN: | FileCheck %s --check-prefix=CHECK-NO-PIC // RUN: %clang -c %s -target armv7-apple-ios -fapple-kext -miphoneos-version-min=6.0.0 -static -### 2>&1 \ // RUN: | FileCheck %s --check-prefix=CHECK-NO-PIC +// RUN: %clang -c %s -target armv7-apple-unknown-macho -static -### 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-NO-PIC // // On OpenBSD, PIE is enabled by default, but can be disabled. // RUN: %clang -c %s -target amd64-pc-openbsd -### 2>&1 \ diff --git a/test/Driver/wasm-toolchain.c b/test/Driver/wasm-toolchain.c index 4d707a0f6c8f..b9685b160192 100644 --- a/test/Driver/wasm-toolchain.c +++ b/test/Driver/wasm-toolchain.c @@ -1,3 +1,44 @@ -// RUN: %clang -### -no-canonical-prefixes -target wasm32-unknown-unknown -x assembler %s 2>&1 | FileCheck -check-prefix=AS_LINK %s -// AS_LINK: clang{{.*}}" "-cc1as" {{.*}} "-o" "[[temp:[^"]*]]" -// AS_LINK: lld{{.*}}" "-flavor" "ld" "[[temp]]" "-o" "a.out" +// A basic clang -cc1 command-line. WebAssembly is somewhat special in +// enabling -ffunction-sections, -fdata-sections, and -fvisibility=hidden by +// default. + +// RUN: %clang %s -### -no-canonical-prefixes -target wasm32-unknown-unknown 2>&1 | FileCheck -check-prefix=CC1 %s +// CC1: clang{{.*}} "-cc1" "-triple" "wasm32-unknown-unknown" {{.*}} "-fvisibility" "hidden" {{.*}} "-ffunction-sections" "-fdata-sections" + +// Ditto, but ensure that a user -fno-function-sections disables the +// default -ffunction-sections. + +// RUN: %clang %s -### -target wasm32-unknown-unknown -fno-function-sections 2>&1 | FileCheck -check-prefix=NO_FUNCTION_SECTIONS %s +// NO_FUNCTION_SECTIONS-NOT: function-sections + +// Ditto, but ensure that a user -fno-data-sections disables the +// default -fdata-sections. + +// RUN: %clang %s -### -target wasm32-unknown-unknown -fno-data-sections 2>&1 | FileCheck -check-prefix=NO_DATA_SECTIONS %s +// NO_DATA_SECTIONS-NOT: data-sections + +// Ditto, but ensure that a user -fvisibility=default disables the default +// -fvisibility=hidden. + +// RUN: %clang %s -### -target wasm32-unknown-unknown -fvisibility=default 2>&1 | FileCheck -check-prefix=FVISIBILITY_DEFAULT %s +// FVISIBILITY_DEFAULT-NOT: hidden + +// A basic C link command-line. + +// RUN: %clang -### -no-canonical-prefixes -target wasm32-unknown-unknown %s 2>&1 | FileCheck -check-prefix=LINK %s +// LINK: clang{{.*}}" "-cc1" {{.*}} "-o" "[[temp:[^"]*]]" +// LINK: lld{{.*}}" "-flavor" "ld" "[[temp]]" "-o" "a.out" + +// A basic C link command-line with optimization. WebAssembly is somewhat +// special in enabling --gc-sections by default. + +// RUN: %clang -### -O2 -no-canonical-prefixes -target wasm32-unknown-unknown %s 2>&1 | FileCheck -check-prefix=LINK_OPT %s +// LINK_OPT: clang{{.*}}" "-cc1" {{.*}} "-o" "[[temp:[^"]*]]" +// LINK_OPT: lld{{.*}}" "-flavor" "ld" "--gc-sections" "[[temp]]" "-o" "a.out" + +// Ditto, but ensure that a user --no-gc-sections comes after the +// default --gc-sections. + +// RUN: %clang -### -O2 -no-canonical-prefixes -target wasm32-unknown-unknown -Wl,--no-gc-sections %s 2>&1 | FileCheck -check-prefix=NO_GC_SECTIONS %s +// NO_GC_SECTIONS: clang{{.*}}" "-cc1" {{.*}} "-o" "[[temp:[^"]*]]" +// NO_GC_SECTIONS: lld{{.*}}" "-flavor" "ld" "--gc-sections" "--no-gc-sections" "[[temp]]" "-o" "a.out" diff --git a/test/Driver/wasm32-unknown-unknown.cpp b/test/Driver/wasm32-unknown-unknown.cpp index c47428796dc9..3f44d93df570 100644 --- a/test/Driver/wasm32-unknown-unknown.cpp +++ b/test/Driver/wasm32-unknown-unknown.cpp @@ -13,34 +13,34 @@ typedef __PTRDIFF_TYPE__ ptrdiff_t; extern "C" { -// CHECK: @align_c = global i32 1 +// CHECK: @align_c = hidden global i32 1 int align_c = __alignof(char); -// CHECK: @align_s = global i32 2 +// CHECK: @align_s = hidden global i32 2 int align_s = __alignof(short); -// CHECK: @align_i = global i32 4 +// CHECK: @align_i = hidden global i32 4 int align_i = __alignof(int); -// CHECK: @align_l = global i32 4 +// CHECK: @align_l = hidden global i32 4 int align_l = __alignof(long); -// CHECK: @align_ll = global i32 8 +// CHECK: @align_ll = hidden global i32 8 int align_ll = __alignof(long long); -// CHECK: @align_p = global i32 4 +// CHECK: @align_p = hidden global i32 4 int align_p = __alignof(void*); -// CHECK: @align_f = global i32 4 +// CHECK: @align_f = hidden global i32 4 int align_f = __alignof(float); -// CHECK: @align_d = global i32 8 +// CHECK: @align_d = hidden global i32 8 int align_d = __alignof(double); -// CHECK: @align_ld = global i32 16 +// CHECK: @align_ld = hidden global i32 16 int align_ld = __alignof(long double); -// CHECK: @align_vl = global i32 4 +// CHECK: @align_vl = hidden global i32 4 int align_vl = __alignof(va_list); // CHECK: _GNU_SOURCEdefined diff --git a/test/Driver/wasm64-unknown-unknown.cpp b/test/Driver/wasm64-unknown-unknown.cpp index c33f4e56a65f..6162759884a8 100644 --- a/test/Driver/wasm64-unknown-unknown.cpp +++ b/test/Driver/wasm64-unknown-unknown.cpp @@ -13,34 +13,34 @@ typedef __PTRDIFF_TYPE__ ptrdiff_t; extern "C" { -// CHECK: @align_c = global i32 1 +// CHECK: @align_c = hidden global i32 1 int align_c = __alignof(char); -// CHECK: @align_s = global i32 2 +// CHECK: @align_s = hidden global i32 2 int align_s = __alignof(short); -// CHECK: @align_i = global i32 4 +// CHECK: @align_i = hidden global i32 4 int align_i = __alignof(int); -// CHECK: @align_l = global i32 8 +// CHECK: @align_l = hidden global i32 8 int align_l = __alignof(long); -// CHECK: @align_ll = global i32 8 +// CHECK: @align_ll = hidden global i32 8 int align_ll = __alignof(long long); -// CHECK: @align_p = global i32 8 +// CHECK: @align_p = hidden global i32 8 int align_p = __alignof(void*); -// CHECK: @align_f = global i32 4 +// CHECK: @align_f = hidden global i32 4 int align_f = __alignof(float); -// CHECK: @align_d = global i32 8 +// CHECK: @align_d = hidden global i32 8 int align_d = __alignof(double); -// CHECK: @align_ld = global i32 16 +// CHECK: @align_ld = hidden global i32 16 int align_ld = __alignof(long double); -// CHECK: @align_vl = global i32 8 +// CHECK: @align_vl = hidden global i32 8 int align_vl = __alignof(va_list); // CHECK: _GNU_SOURCEdefined diff --git a/test/Index/print-type-declaration.cpp b/test/Index/print-type-declaration.cpp new file mode 100644 index 000000000000..31c0a73fcd06 --- /dev/null +++ b/test/Index/print-type-declaration.cpp @@ -0,0 +1,12 @@ + +class Test{}; + +int main() +{ + auto a = Test(); + auto b = a; +} + +// RUN: c-index-test -test-print-type-declaration -std=c++11 %s | FileCheck %s +// CHECK: VarDecl=a:6:8 (Definition) [typedeclaration=Test] [typekind=Record] +// CHECK: VarDecl=b:7:8 (Definition) [typedeclaration=Test] [typekind=Record] diff --git a/test/Misc/ast-dump-lookups.cpp b/test/Misc/ast-dump-lookups.cpp index 5c6da48b3afb..2d235010cb73 100644 --- a/test/Misc/ast-dump-lookups.cpp +++ b/test/Misc/ast-dump-lookups.cpp @@ -1,16 +1,31 @@ // RUN: %clang_cc1 -std=c++11 -ast-dump -ast-dump-filter Test %s | FileCheck -check-prefix DECLS %s // RUN: %clang_cc1 -std=c++11 -ast-dump-lookups -ast-dump-filter Test %s | FileCheck -check-prefix LOOKUPS %s // RUN: %clang_cc1 -std=c++11 -ast-dump -ast-dump-lookups -ast-dump-filter Test %s | FileCheck -check-prefix DECLS-LOOKUPS %s +// RUN: %clang_cc1 -std=c++11 -DPRAGMA -fsyntax-only %s 2>&1 | FileCheck -check-prefix PRAGMA %s namespace Test { + typedef int T; extern int a; int a = 0; } +#ifdef PRAGMA +#pragma clang __debug dump Test +// PRAGMA: lookup results for Test: +// PRAGMA-NEXT: NamespaceDecl {{.*}} Test +// PRAGMA-NEXT: |-TypedefDecl {{.*}} T 'int' +// PRAGMA-NEXT: | `-BuiltinType {{.*}} 'int' +// PRAGMA-NEXT: |-VarDecl [[EXTERN_A:0x[^ ]*]] {{.*}} a 'int' extern +// PRAGMA-NEXT: `-VarDecl {{.*}} prev [[EXTERN_A]] {{.*}} a 'int' cinit +// PRAGMA-NEXT: `-IntegerLiteral {{.*}} 'int' 0 +#endif + namespace Test { } // DECLS: Dumping Test: // DECLS-NEXT: NamespaceDecl {{.*}} Test +// DECLS-NEXT: |-TypedefDecl {{.*}} T 'int' +// DECLS-NEXT: | `-BuiltinType {{.*}} 'int' // DECLS-NEXT: |-VarDecl [[EXTERN_A:0x[^ ]*]] {{.*}} a 'int' extern // DECLS-NEXT: `-VarDecl {{.*}} prev [[EXTERN_A]] {{.*}} a 'int' cinit // DECLS-NEXT: `-IntegerLiteral {{.*}} 'int' 0 @@ -20,15 +35,15 @@ namespace Test { } // LOOKUPS: Dumping Test: // LOOKUPS-NEXT: StoredDeclsMap Namespace {{.*}} 'Test' -// LOOKUPS-NEXT: `-DeclarationName 'a' -// LOOKUPS-NEXT: `-Var {{.*}} 'a' 'int' +// LOOKUPS: DeclarationName 'a' +// LOOKUPS-NEXT: `-Var {{.*}} 'a' 'int' // // LOOKUPS: Dumping Test: // LOOKUPS-NEXT: Lookup map is in primary DeclContext // DECLS-LOOKUPS: Dumping Test: // DECLS-LOOKUPS-NEXT: StoredDeclsMap Namespace {{.*}} 'Test' -// DECLS-LOOKUPS-NEXT: `-DeclarationName 'a' +// DECLS-LOOKUPS: -DeclarationName 'a' // DECLS-LOOKUPS-NEXT: `-Var [[A:[^ ]*]] 'a' 'int' // DECLS-LOOKUPS-NEXT: |-VarDecl [[EXTERN_A:0x[^ ]*]] {{.*}} a 'int' extern // DECLS-LOOKUPS-NEXT: `-VarDecl [[A]] prev [[EXTERN_A]] {{.*}} a 'int' cinit diff --git a/test/Misc/ast-print-char-literal.cpp b/test/Misc/ast-print-char-literal.cpp new file mode 100644 index 000000000000..bb5daa2444da --- /dev/null +++ b/test/Misc/ast-print-char-literal.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -ast-print -std=c++1z %s -o - | FileCheck %s + +char c = u8'1'; +char d = '1'; +char e = U'1'; +char f = L'1'; +char g = u'1'; + +template +void h(); + +void i() { + h(); +} + +// CHECK: char c = u8'1'; +// CHECK-NEXT: char d = '1'; +// CHECK-NEXT: char e = U'1'; +// CHECK-NEXT: char f = L'1'; +// CHECK-NEXT: char g = u'1'; + +// CHECK: template + +// CHECK: h(); diff --git a/test/Modules/Inputs/DebugCXX.h b/test/Modules/Inputs/DebugCXX.h index 6ef4445cb971..b6a52579fc3a 100644 --- a/test/Modules/Inputs/DebugCXX.h +++ b/test/Modules/Inputs/DebugCXX.h @@ -17,7 +17,7 @@ namespace DebugCXX { e2 = '2' }; - // Templates (instatiations). + // Templates (instantiations). template struct traits {}; template @@ -50,3 +50,11 @@ namespace DebugCXX { typedef A B; void foo(B) {} } + +// Virtual class with a forward declaration. +class FwdVirtual; +class FwdVirtual { + virtual ~FwdVirtual() {} +}; + +struct PureForwardDecl; diff --git a/test/Modules/Inputs/dummy.h b/test/Modules/Inputs/dummy.h index 6e1ac74e44fb..cad83154dc2e 100644 --- a/test/Modules/Inputs/dummy.h +++ b/test/Modules/Inputs/dummy.h @@ -1,3 +1,5 @@ // This module only exists to make local decl IDs and global decl IDs different. - +#ifndef DUMMY_H +#define DUMMY_H struct Dummy {} extern *dummy1, *dummy2, *dummy3; +#endif diff --git a/test/Modules/Inputs/using-decl-redecl/a.h b/test/Modules/Inputs/using-decl-redecl/a.h index 477546945c09..eaa1876aac68 100644 --- a/test/Modules/Inputs/using-decl-redecl/a.h +++ b/test/Modules/Inputs/using-decl-redecl/a.h @@ -1,2 +1,3 @@ struct string {}; -namespace N { typedef ::string clstring; } +const int n = 0; +namespace N { typedef ::string clstring; using ::n; } diff --git a/test/Modules/Inputs/using-decl-redecl/d.h b/test/Modules/Inputs/using-decl-redecl/d.h new file mode 100644 index 000000000000..2243de1baf9a --- /dev/null +++ b/test/Modules/Inputs/using-decl-redecl/d.h @@ -0,0 +1 @@ +#include "a.h" diff --git a/test/Modules/Inputs/using-decl-redecl/module.modulemap b/test/Modules/Inputs/using-decl-redecl/module.modulemap index bd6ea830c2d4..a2ebc1767645 100644 --- a/test/Modules/Inputs/using-decl-redecl/module.modulemap +++ b/test/Modules/Inputs/using-decl-redecl/module.modulemap @@ -1,3 +1,4 @@ module a { header "a.h" } -module b { header "b.h" export * } -module c { header "c.h" export * } +module b { header "b.h" export a } +module c { header "c.h" export a export b } +module d { header "d.h" } diff --git a/test/Modules/ModuleDebugInfo.cpp b/test/Modules/ModuleDebugInfo.cpp index 82500f0d162d..bbe36cb225d0 100644 --- a/test/Modules/ModuleDebugInfo.cpp +++ b/test/Modules/ModuleDebugInfo.cpp @@ -23,22 +23,34 @@ // CHECK-SAME: isOptimized: false, // CHECK-SAME-NOT: splitDebugFilename: // CHECK-DWO: dwoId: + // CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "Enum" // CHECK-SAME: identifier: "_ZTSN8DebugCXX4EnumE") // CHECK: !DINamespace(name: "DebugCXX" + // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "Struct" // CHECK-SAME: identifier: "_ZTSN8DebugCXX6StructE") + // CHECK: !DICompositeType(tag: DW_TAG_class_type, // CHECK-SAME: name: "Template >" // CHECK-SAME: identifier: "_ZTSN8DebugCXX8TemplateIiNS_6traitsIiEEEE") + +// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "A" +// CHECK-SAME: identifier: "_ZTSN8DebugCXX1AIJvEEE") + // CHECK: !DICompositeType(tag: DW_TAG_class_type, // CHECK-SAME: name: "Template >" // CHECK-SAME: identifier: "_ZTSN8DebugCXX8TemplateIfNS_6traitsIfEEEE") -// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "A" -// CHECK-SAME: identifier: "_ZTSN8DebugCXX1AIJvEEE") + +// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "FwdVirtual" +// CHECK-SAME: elements: +// CHECK-SAME: identifier: "_ZTS10FwdVirtual") +// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "_vptr$FwdVirtual" + // CHECK: !DIDerivedType(tag: DW_TAG_typedef, name: "FloatInstatiation" // no mangled name here yet. + // CHECK: !DIDerivedType(tag: DW_TAG_typedef, name: "B", // no mangled name here yet. -// CHECK-NEG-NOT: "_ZTSN8DebugCXX8TemplateIlNS_6traitsIlEEEE" +// CHECK-NEG-NOT: !DICompositeType(tag: DW_TAG_structure_type, name: "PureForwardDecl" diff --git a/test/Modules/modular_maps.cpp b/test/Modules/modular_maps.cpp index 3b6afc7552d6..fc44131d4587 100644 --- a/test/Modules/modular_maps.cpp +++ b/test/Modules/modular_maps.cpp @@ -16,4 +16,4 @@ #include "b.h" // expected-error {{private header}} @import C; const int v = a + c + x; -const int val = a + b + c + x; // expected-error {{undeclared identifier}} +const int val = a + b + c + x; diff --git a/test/Modules/separate_map_tree.cpp b/test/Modules/separate_map_tree.cpp index 5a1fff4efc70..a5cb9888a600 100644 --- a/test/Modules/separate_map_tree.cpp +++ b/test/Modules/separate_map_tree.cpp @@ -5,4 +5,4 @@ #include "public-in-b.h" // expected-error {{private header}} #include "public-in-c.h" #include "private-in-c.h" // expected-error {{private header}} -const int val = common + b + c + c_; // expected-error {{undeclared identifier}} +const int val = common + b + c + c_; diff --git a/test/Modules/tag-injection.c b/test/Modules/tag-injection.c new file mode 100644 index 000000000000..5bb15477e2e2 --- /dev/null +++ b/test/Modules/tag-injection.c @@ -0,0 +1,18 @@ +// RUN: rm -rf %t +// RUN: mkdir %t +// RUN: echo 'struct a;' > %t/a.h +// RUN: echo 'struct b {}; void foo(struct b*);' > %t/b.h +// RUN: echo 'module X { module a { header "a.h" } module b { header "b.h" } }' > %t/x.modulemap +// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -fmodule-map-file=%t/x.modulemap %s -I%t -verify + +#include "a.h" + +void f(struct a *p); + +// FIXME: We should warn that 'b' will not be visible outside of this function, +// but we merge this 'b' with X.b's 'b' because we don't yet implement C's +// "compatible types" rule. +void g(struct b *p); + +struct b b; // expected-error {{definition of 'b' must be imported from module 'X.b' before it is required}} +// expected-note@b.h:1 {{here}} diff --git a/test/Modules/tag-injection.cpp b/test/Modules/tag-injection.cpp index 75c8b5fecdb4..e55598b06202 100644 --- a/test/Modules/tag-injection.cpp +++ b/test/Modules/tag-injection.cpp @@ -1,12 +1,15 @@ // RUN: rm -rf %t // RUN: mkdir %t -// RUN: touch %t/a.h -// RUN: echo 'struct X {};' > %t/b.h +// RUN: echo 'struct tm;' > %t/a.h +// RUN: echo 'struct X {}; void foo(struct tm*);' > %t/b.h // RUN: echo 'module X { module a { header "a.h" } module b { header "b.h" } }' > %t/x.modulemap +// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -x c++ -fmodule-map-file=%t/x.modulemap %s -I%t -verify -std=c++11 // RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -x c++ -fmodule-map-file=%t/x.modulemap %s -I%t -verify -fmodules-local-submodule-visibility -std=c++11 #include "a.h" +using ::tm; + struct A { // This use of 'struct X' makes the declaration (but not definition) of X visible. virtual void f(struct X *p); diff --git a/test/Modules/using-decl-redecl.cpp b/test/Modules/using-decl-redecl.cpp index 0e78cec1188f..0524052fce5b 100644 --- a/test/Modules/using-decl-redecl.cpp +++ b/test/Modules/using-decl-redecl.cpp @@ -2,10 +2,20 @@ // RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t \ // RUN: -fmodule-map-file=%S/Inputs/using-decl-redecl/module.modulemap \ // RUN: -I%S/Inputs/using-decl-redecl \ +// RUN: -Wno-modules-ambiguous-internal-linkage \ // RUN: -verify %s + +#include "d.h" + +const int n = 0; +namespace M { using ::n; } + #include "c.h" + N::clstring y = b; // Use a typo to trigger import of all declarations in N. N::clstrinh s; // expected-error {{did you mean 'clstring'}} -// expected-note@a.h:2 {{here}} +// expected-note@a.h:3 {{here}} + +namespace M { using N::n; } diff --git a/test/OpenMP/barrier_ast_print.cpp b/test/OpenMP/barrier_ast_print.cpp index fbb478bfb6b7..062df80a226e 100644 --- a/test/OpenMP/barrier_ast_print.cpp +++ b/test/OpenMP/barrier_ast_print.cpp @@ -12,6 +12,15 @@ template T tmain(T argc) { static T a; #pragma omp barrier + switch (argc) { + case 0: +#pragma omp barrier + break; + default: +#pragma omp barrier +#pragma omp barrier + break; + } return a + argc; } // CHECK: static int a; @@ -20,12 +29,39 @@ T tmain(T argc) { // CHECK-NEXT: #pragma omp barrier // CHECK: static T a; // CHECK-NEXT: #pragma omp barrier +// CHECK-NEXT: switch (argc) { +// CHECK-NEXT: case 0: +// CHECK-NEXT: #pragma omp barrier +// CHECK-NEXT: break; +// CHECK-NEXT: default: +// CHECK-NEXT: #pragma omp barrier +// CHECK-NEXT: #pragma omp barrier +// CHECK-NEXT: break; +// CHECK-NEXT: } int main(int argc, char **argv) { static int a; // CHECK: static int a; #pragma omp barrier // CHECK-NEXT: #pragma omp barrier + switch (argc) { + case 0: +#pragma omp barrier +#pragma omp barrier + break; + default: +#pragma omp barrier + break; + } +// CHECK-NEXT: switch (argc) { +// CHECK-NEXT: case 0: +// CHECK-NEXT: #pragma omp barrier +// CHECK-NEXT: #pragma omp barrier +// CHECK-NEXT: break; +// CHECK-NEXT: default: +// CHECK-NEXT: #pragma omp barrier +// CHECK-NEXT: break; +// CHECK-NEXT: } return tmain(argc) + tmain(argv[0][0]) + a; } diff --git a/test/OpenMP/barrier_messages.cpp b/test/OpenMP/barrier_messages.cpp index 4dc6480a57e2..7d79445d2857 100644 --- a/test/OpenMP/barrier_messages.cpp +++ b/test/OpenMP/barrier_messages.cpp @@ -27,7 +27,7 @@ T tmain(T argc) { #pragma omp barrier // expected-error {{'#pragma omp barrier' cannot be an immediate substatement}} switch (argc) case 1: -#pragma omp barrier // expected-error {{'#pragma omp barrier' cannot be an immediate substatement}} +#pragma omp barrier switch (argc) case 1: { #pragma omp barrier @@ -35,7 +35,7 @@ T tmain(T argc) { switch (argc) { #pragma omp barrier case 1: -#pragma omp barrier // expected-error {{'#pragma omp barrier' cannot be an immediate substatement}} +#pragma omp barrier break; default: { #pragma omp barrier @@ -81,7 +81,7 @@ int main(int argc, char **argv) { #pragma omp barrier // expected-error {{'#pragma omp barrier' cannot be an immediate substatement}} switch (argc) case 1: -#pragma omp barrier // expected-error {{'#pragma omp barrier' cannot be an immediate substatement}} +#pragma omp barrier switch (argc) case 1: { #pragma omp barrier @@ -89,7 +89,7 @@ int main(int argc, char **argv) { switch (argc) { #pragma omp barrier case 1: -#pragma omp barrier // expected-error {{'#pragma omp barrier' cannot be an immediate substatement}} +#pragma omp barrier break; default: { #pragma omp barrier diff --git a/test/OpenMP/cancel_messages.cpp b/test/OpenMP/cancel_messages.cpp index 07088387cb4f..e23b5c337bc8 100644 --- a/test/OpenMP/cancel_messages.cpp +++ b/test/OpenMP/cancel_messages.cpp @@ -53,7 +53,7 @@ int main(int argc, char **argv) { #pragma omp cancel parallel // expected-error {{'#pragma omp cancel' cannot be an immediate substatement}} switch (argc) case 1: -#pragma omp cancel sections // expected-error {{'#pragma omp cancel' cannot be an immediate substatement}} +#pragma omp cancel sections switch (argc) case 1: { #pragma omp cancel for @@ -61,7 +61,7 @@ int main(int argc, char **argv) { switch (argc) { #pragma omp cancel taskgroup case 1: -#pragma omp cancel parallel // expected-error {{'#pragma omp cancel' cannot be an immediate substatement}} +#pragma omp cancel parallel break; default: { #pragma omp cancel sections diff --git a/test/OpenMP/cancellation_point_messages.cpp b/test/OpenMP/cancellation_point_messages.cpp index d25cb6113d16..2324915e83f8 100644 --- a/test/OpenMP/cancellation_point_messages.cpp +++ b/test/OpenMP/cancellation_point_messages.cpp @@ -53,7 +53,7 @@ int main(int argc, char **argv) { #pragma omp cancellation point parallel // expected-error {{'#pragma omp cancellation point' cannot be an immediate substatement}} switch (argc) case 1: -#pragma omp cancellation point sections // expected-error {{'#pragma omp cancellation point' cannot be an immediate substatement}} +#pragma omp cancellation point sections switch (argc) case 1: { #pragma omp cancellation point for @@ -61,7 +61,7 @@ int main(int argc, char **argv) { switch (argc) { #pragma omp cancellation point taskgroup case 1: -#pragma omp cancellation point parallel // expected-error {{'#pragma omp cancellation point' cannot be an immediate substatement}} +#pragma omp cancellation point parallel break; default: { #pragma omp cancellation point sections diff --git a/test/OpenMP/flush_messages.cpp b/test/OpenMP/flush_messages.cpp index 2f87a2938476..1c086a3f3fa4 100644 --- a/test/OpenMP/flush_messages.cpp +++ b/test/OpenMP/flush_messages.cpp @@ -31,7 +31,7 @@ T tmain(T argc) { #pragma omp flush // expected-error {{'#pragma omp flush' cannot be an immediate substatement}} switch (argc) case 1: -#pragma omp flush // expected-error {{'#pragma omp flush' cannot be an immediate substatement}} +#pragma omp flush switch (argc) case 1: { #pragma omp flush @@ -39,7 +39,7 @@ T tmain(T argc) { switch (argc) { #pragma omp flush case 1: -#pragma omp flush // expected-error {{'#pragma omp flush' cannot be an immediate substatement}} +#pragma omp flush break; default: { #pragma omp flush @@ -95,7 +95,7 @@ int main(int argc, char **argv) { #pragma omp flush // expected-error {{'#pragma omp flush' cannot be an immediate substatement}} switch (argc) case 1: -#pragma omp flush // expected-error {{'#pragma omp flush' cannot be an immediate substatement}} +#pragma omp flush switch (argc) case 1: { #pragma omp flush @@ -103,7 +103,7 @@ int main(int argc, char **argv) { switch (argc) { #pragma omp flush case 1: -#pragma omp flush // expected-error {{'#pragma omp flush' cannot be an immediate substatement}} +#pragma omp flush break; default: { #pragma omp flush diff --git a/test/OpenMP/target_codegen_registration.cpp b/test/OpenMP/target_codegen_registration.cpp index 0c9bba6df8bd..7d515bb64d90 100644 --- a/test/OpenMP/target_codegen_registration.cpp +++ b/test/OpenMP/target_codegen_registration.cpp @@ -407,31 +407,31 @@ int bar(int a){ // Check metadata is properly generated: // CHECK: !omp_offload.info = !{!{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}} -// CHECK-DAG = !{i32 0, i32 [[DEVID:[0-9]+]], i32 [[FILEID:-?[0-9]+]], !"_ZN2SB3fooEv", i32 160, i32 13, i32 {{[0-9]}}+} -// CHECK-DAG = !{i32 0, i32 [[DEVID]], i32 [[FILEID]] !"_ZN2SDD2Ev", i32 210, i32 13, i32 {{[0-9]}}+} -// CHECK-DAG = !{i32 0, i32 [[DEVID]], i32 [[FILEID]] !"_ZN2SEC2Ev", i32 226, i32 13, i32 {{[0-9]}}+} -// CHECK-DAG = !{i32 0, i32 [[DEVID]], i32 [[FILEID]] !"_ZN2SED2Ev", i32 232, i32 13, i32 {{[0-9]}}+} -// CHECK-DAG = !{i32 0, i32 [[DEVID]], i32 [[FILEID]] !"_ZN2STILi1000EE3fooEv", i32 243, i32 13, i32 {{[0-9]}}+} -// CHECK-DAG = !{i32 0, i32 [[DEVID]], i32 [[FILEID]] !"_ZN2STILi100EEC2Ev", i32 249, i32 13, i32 {{[0-9]}}+} -// CHECK-DAG = !{i32 0, i32 [[DEVID]], i32 [[FILEID]] !"_Z3bari", i32 352, i32 11, i32 {{[0-9]}}+} -// CHECK-DAG = !{i32 0, i32 [[DEVID]], i32 [[FILEID]] !"_ZN2STILi100EED2Ev", i32 255, i32 13, i32 {{[0-9]}}+} -// CHECK-DAG = !{i32 0, i32 [[DEVID]], i32 [[FILEID]] !"_ZN2STILi1000EEC2Ev", i32 249, i32 13, i32 {{[0-9]}}+} -// CHECK-DAG = !{i32 0, i32 [[DEVID]], i32 [[FILEID]] !"_ZN2STILi1000EED2Ev", i32 255, i32 13, i32 {{[0-9]}}+} -// CHECK-DAG = !{i32 0, i32 [[DEVID]], i32 [[FILEID]] !"_ZN2STILi100EE3fooEv", i32 243, i32 13, i32 {{[0-9]}}+} -// CHECK-DAG = !{i32 0, i32 [[DEVID]], i32 [[FILEID]] !"_ZN2SCC2Ev", i32 185, i32 13, i32 {{[0-9]}}+} +// CHECK-DAG: = !{i32 0, i32 [[DEVID:-?[0-9]+]], i32 [[FILEID:-?[0-9]+]], !"_ZN2SB3fooEv", i32 193, i32 13, i32 {{[0-9]+}}} +// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SDD1Ev", i32 243, i32 13, i32 {{[0-9]+}}} +// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SEC1Ev", i32 259, i32 13, i32 {{[0-9]+}}} +// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SED1Ev", i32 265, i32 13, i32 {{[0-9]+}}} +// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EE3fooEv", i32 276, i32 13, i32 {{[0-9]+}}} +// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EEC1Ev", i32 282, i32 13, i32 {{[0-9]+}}} +// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_Z3bari", i32 402, i32 11, i32 {{[0-9]+}}} +// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EED1Ev", i32 288, i32 13, i32 {{[0-9]+}}} +// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EEC1Ev", i32 282, i32 13, i32 {{[0-9]+}}} +// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EED1Ev", i32 288, i32 13, i32 {{[0-9]+}}} +// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EE3fooEv", i32 276, i32 13, i32 {{[0-9]+}}} +// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SCC1Ev", i32 218, i32 13, i32 {{[0-9]+}}} // TCHECK: !omp_offload.info = !{!{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}} -// TCHECK-DAG = !{i32 0, i32 [[DEVID:[0-9]+]], i32 [[FILEID:-?[0-9]+]], !"_ZN2SB3fooEv", i32 160, i32 13, i32 {{[0-9]}}+} -// TCHECK-DAG = !{i32 0, i32 [[DEVID]], i32 [[FILEID]] !"_ZN2SDD2Ev", i32 210, i32 13, i32 {{[0-9]}}+} -// TCHECK-DAG = !{i32 0, i32 [[DEVID]], i32 [[FILEID]] !"_ZN2SEC2Ev", i32 226, i32 13, i32 {{[0-9]}}+} -// TCHECK-DAG = !{i32 0, i32 [[DEVID]], i32 [[FILEID]] !"_ZN2SED2Ev", i32 232, i32 13, i32 {{[0-9]}}+} -// TCHECK-DAG = !{i32 0, i32 [[DEVID]], i32 [[FILEID]] !"_ZN2STILi1000EE3fooEv", i32 243, i32 13, i32 {{[0-9]}}+} -// TCHECK-DAG = !{i32 0, i32 [[DEVID]], i32 [[FILEID]] !"_ZN2STILi100EEC2Ev", i32 249, i32 13, i32 {{[0-9]}}+} -// TCHECK-DAG = !{i32 0, i32 [[DEVID]], i32 [[FILEID]] !"_Z3bari", i32 352, i32 11, i32 {{[0-9]}}+} -// TCHECK-DAG = !{i32 0, i32 [[DEVID]], i32 [[FILEID]] !"_ZN2STILi100EED2Ev", i32 255, i32 13, i32 {{[0-9]}}+} -// TCHECK-DAG = !{i32 0, i32 [[DEVID]], i32 [[FILEID]] !"_ZN2STILi1000EEC2Ev", i32 249, i32 13, i32 {{[0-9]}}+} -// TCHECK-DAG = !{i32 0, i32 [[DEVID]], i32 [[FILEID]] !"_ZN2STILi1000EED2Ev", i32 255, i32 13, i32 {{[0-9]}}+} -// TCHECK-DAG = !{i32 0, i32 [[DEVID]], i32 [[FILEID]] !"_ZN2STILi100EE3fooEv", i32 243, i32 13, i32 {{[0-9]}}+} -// TCHECK-DAG = !{i32 0, i32 [[DEVID]], i32 [[FILEID]] !"_ZN2SCC2Ev", i32 185, i32 13, i32 {{[0-9]}}+} +// TCHECK-DAG: = !{i32 0, i32 [[DEVID:-?[0-9]+]], i32 [[FILEID:-?[0-9]+]], !"_ZN2SB3fooEv", i32 193, i32 13, i32 {{[0-9]+}}} +// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SDD1Ev", i32 243, i32 13, i32 {{[0-9]+}}} +// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SEC1Ev", i32 259, i32 13, i32 {{[0-9]+}}} +// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SED1Ev", i32 265, i32 13, i32 {{[0-9]+}}} +// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EE3fooEv", i32 276, i32 13, i32 {{[0-9]+}}} +// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EEC1Ev", i32 282, i32 13, i32 {{[0-9]+}}} +// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_Z3bari", i32 402, i32 11, i32 {{[0-9]+}}} +// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EED1Ev", i32 288, i32 13, i32 {{[0-9]+}}} +// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EEC1Ev", i32 282, i32 13, i32 {{[0-9]+}}} +// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EED1Ev", i32 288, i32 13, i32 {{[0-9]+}}} +// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EE3fooEv", i32 276, i32 13, i32 {{[0-9]+}}} +// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SCC1Ev", i32 218, i32 13, i32 {{[0-9]+}}} #endif diff --git a/test/OpenMP/target_codegen_registration_naming.cpp b/test/OpenMP/target_codegen_registration_naming.cpp index 6ab9bf1aa94e..ab7a469aba4d 100644 --- a/test/OpenMP/target_codegen_registration_naming.cpp +++ b/test/OpenMP/target_codegen_registration_naming.cpp @@ -57,10 +57,10 @@ int nested(int a){ // Check metadata is properly generated: // CHECK: !omp_offload.info = !{!{{[0-9]+}}, !{{[0-9]+}}} -// CHECK-DAG: = !{i32 0, i32 {{[0-9]+}}, i32 {{-?[0-9]+}}, !"[[NNAME]]", i32 [[T1L]], i32 [[T1C]], i32 {{[0-9]+}}} -// CHECK-DAG: = !{i32 0, i32 {{[0-9]+}}, i32 {{-?[0-9]+}}, !"[[NNAME]]", i32 [[T2L]], i32 [[T2C]], i32 {{[0-9]+}}} +// CHECK-DAG: = !{i32 0, i32 {{-?[0-9]+}}, i32 {{-?[0-9]+}}, !"[[NNAME]]", i32 [[T1L]], i32 [[T1C]], i32 {{[0-9]+}}} +// CHECK-DAG: = !{i32 0, i32 {{-?[0-9]+}}, i32 {{-?[0-9]+}}, !"[[NNAME]]", i32 [[T2L]], i32 [[T2C]], i32 {{[0-9]+}}} // TCHECK: !omp_offload.info = !{!{{[0-9]+}}, !{{[0-9]+}}} -// TCHECK-DAG: = !{i32 0, i32 {{[0-9]+}}, i32 {{-?[0-9]+}}, !"[[NNAME]]", i32 [[T1L]], i32 [[T1C]], i32 {{[0-9]+}}} -// TCHECK-DAG: = !{i32 0, i32 {{[0-9]+}}, i32 {{-?[0-9]+}}, !"[[NNAME]]", i32 [[T2L]], i32 [[T2C]], i32 {{[0-9]+}}} +// TCHECK-DAG: = !{i32 0, i32 {{-?[0-9]+}}, i32 {{-?[0-9]+}}, !"[[NNAME]]", i32 [[T1L]], i32 [[T1C]], i32 {{[0-9]+}}} +// TCHECK-DAG: = !{i32 0, i32 {{-?[0-9]+}}, i32 {{-?[0-9]+}}, !"[[NNAME]]", i32 [[T2L]], i32 [[T2C]], i32 {{[0-9]+}}} #endif diff --git a/test/OpenMP/taskwait_messages.cpp b/test/OpenMP/taskwait_messages.cpp index 084051354045..06e8e6b8bdf2 100644 --- a/test/OpenMP/taskwait_messages.cpp +++ b/test/OpenMP/taskwait_messages.cpp @@ -27,7 +27,7 @@ T tmain(T argc) { #pragma omp taskwait // expected-error {{'#pragma omp taskwait' cannot be an immediate substatement}} switch (argc) case 1: -#pragma omp taskwait // expected-error {{'#pragma omp taskwait' cannot be an immediate substatement}} +#pragma omp taskwait switch (argc) case 1: { #pragma omp taskwait @@ -35,7 +35,7 @@ T tmain(T argc) { switch (argc) { #pragma omp taskwait case 1: -#pragma omp taskwait // expected-error {{'#pragma omp taskwait' cannot be an immediate substatement}} +#pragma omp taskwait break; default: { #pragma omp taskwait @@ -81,7 +81,7 @@ int main(int argc, char **argv) { #pragma omp taskwait // expected-error {{'#pragma omp taskwait' cannot be an immediate substatement}} switch (argc) case 1: -#pragma omp taskwait // expected-error {{'#pragma omp taskwait' cannot be an immediate substatement}} +#pragma omp taskwait switch (argc) case 1: { #pragma omp taskwait @@ -89,7 +89,7 @@ int main(int argc, char **argv) { switch (argc) { #pragma omp taskwait case 1: -#pragma omp taskwait // expected-error {{'#pragma omp taskwait' cannot be an immediate substatement}} +#pragma omp taskwait break; default: { #pragma omp taskwait diff --git a/test/OpenMP/taskyield_messages.cpp b/test/OpenMP/taskyield_messages.cpp index 23c0b5339012..cfeaa63815b3 100644 --- a/test/OpenMP/taskyield_messages.cpp +++ b/test/OpenMP/taskyield_messages.cpp @@ -27,7 +27,7 @@ T tmain(T argc) { #pragma omp taskyield // expected-error {{'#pragma omp taskyield' cannot be an immediate substatement}} switch (argc) case 1: -#pragma omp taskyield // expected-error {{'#pragma omp taskyield' cannot be an immediate substatement}} +#pragma omp taskyield switch (argc) case 1: { #pragma omp taskyield @@ -35,7 +35,7 @@ T tmain(T argc) { switch (argc) { #pragma omp taskyield case 1: -#pragma omp taskyield // expected-error {{'#pragma omp taskyield' cannot be an immediate substatement}} +#pragma omp taskyield break; default: { #pragma omp taskyield @@ -81,7 +81,7 @@ int main(int argc, char **argv) { #pragma omp taskyield // expected-error {{'#pragma omp taskyield' cannot be an immediate substatement}} switch (argc) case 1: -#pragma omp taskyield // expected-error {{'#pragma omp taskyield' cannot be an immediate substatement}} +#pragma omp taskyield switch (argc) case 1: { #pragma omp taskyield @@ -89,7 +89,7 @@ int main(int argc, char **argv) { switch (argc) { #pragma omp taskyield case 1: -#pragma omp taskyield // expected-error {{'#pragma omp taskyield' cannot be an immediate substatement}} +#pragma omp taskyield break; default: { #pragma omp taskyield diff --git a/test/OpenMP/threadprivate_messages.cpp b/test/OpenMP/threadprivate_messages.cpp index f71d58bc52a4..8c442f47ad5e 100644 --- a/test/OpenMP/threadprivate_messages.cpp +++ b/test/OpenMP/threadprivate_messages.cpp @@ -118,6 +118,7 @@ int main(int argc, char **argv) { // expected-note {{'argc' defined here}} static double d1; static double d2; static double d3; // expected-note {{'d3' defined here}} + static double d4; static TestClass LocalClass(y); // expected-error {{variable with local storage in initial value of threadprivate variable}} #pragma omp threadprivate(LocalClass) @@ -133,6 +134,8 @@ int main(int argc, char **argv) { // expected-note {{'argc' defined here}} #pragma omp threadprivate(d3) // expected-error {{'#pragma omp threadprivate' must appear in the scope of the 'd3' variable declaration}} } #pragma omp threadprivate(d3) +label: +#pragma omp threadprivate(d4) // expected-error {{'#pragma omp threadprivate' cannot be an immediate substatement}} #pragma omp threadprivate(a) // expected-error {{'#pragma omp threadprivate' must appear in the scope of the 'a' variable declaration}} return (y); diff --git a/test/PCH/chain-default-argument-instantiation.cpp b/test/PCH/chain-default-argument-instantiation.cpp new file mode 100644 index 000000000000..0accd544a384 --- /dev/null +++ b/test/PCH/chain-default-argument-instantiation.cpp @@ -0,0 +1,50 @@ +// Test default argument instantiation in chained PCH. + +// Without PCH +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -include %s -include %s %s + +// With PCH +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s -chain-include %s -chain-include %s + +// With modules +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -fmodules %s -chain-include %s -chain-include %s + +// expected-no-diagnostics + +#ifndef HEADER1 +#define HEADER1 +//===----------------------------------------------------------------------===// +// Primary header. + +namespace rdar23810407 { + template int f(T t) { + extern T rdar23810407_variable; + return 0; + } + template int g(int a = f([] {})); +} + +//===----------------------------------------------------------------------===// +#elif not defined(HEADER2) +#define HEADER2 +#if !defined(HEADER1) +#error Header inclusion order messed up +#endif + +//===----------------------------------------------------------------------===// +// Dependent header. + +inline void instantiate_once() { + rdar23810407::g(); +} + +//===----------------------------------------------------------------------===// +#else +//===----------------------------------------------------------------------===// + +void test() { + rdar23810407::g(); +} + +//===----------------------------------------------------------------------===// +#endif diff --git a/test/PCH/cxx-char-literal.cpp b/test/PCH/cxx-char-literal.cpp new file mode 100644 index 000000000000..0990517c55be --- /dev/null +++ b/test/PCH/cxx-char-literal.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -emit-pch -std=c++1z -o %t %s +// RUN: %clang_cc1 -std=c++1z -x ast -ast-print %t | FileCheck %s + +// Ensure that character literals are properly surfaced through PCH. + +char a = '0'; +// CHECK: char a = '0'; + +char b = L'1'; +// CHECK: char b = L'1'; + +char c = u8'2'; +// CHECK: char c = u8'2'; + +char d = U'3'; +// CHECK: char d = U'3'; + +char e = u'4'; +// CHECK: char e = u'4'; diff --git a/test/PCH/ocl_types.cl b/test/PCH/ocl_types.cl index d788a3262143..21097c481182 100644 --- a/test/PCH/ocl_types.cl +++ b/test/PCH/ocl_types.cl @@ -1,9 +1,9 @@ // Test this without pch. -// RUN: %clang_cc1 -include %S/ocl_types.h -fsyntax-only %s +// RUN: %clang_cc1 -include %S/ocl_types.h -fsyntax-only %s -cl-std=CL2.0 -D__OPENCL_VERSION__=200 // Test with pch. -// RUN: %clang_cc1 -x cl -emit-pch -o %t %S/ocl_types.h -// RUN: %clang_cc1 -include-pch %t -fsyntax-only %s -ast-print +// RUN: %clang_cc1 -x cl -emit-pch -o %t %S/ocl_types.h -cl-std=CL2.0 -D__OPENCL_VERSION__=200 +// RUN: %clang_cc1 -include-pch %t -fsyntax-only %s -ast-print -cl-std=CL2.0 -D__OPENCL_VERSION__=200 void foo1(img1d_t img); @@ -24,3 +24,15 @@ void foo7(smp_t smp) { void foo8(evt_t evt) { evt_t loc_evt; } + +#if __OPENCL_VERSION__ >= 200 + +void foo9(pipe int P) { + int_pipe_function(P); +} + +void foo10(pipe Person P) { + person_pipe_function(P); +} + +#endif diff --git a/test/PCH/ocl_types.h b/test/PCH/ocl_types.h index 93cf4f66442b..bdc4bb11c1b2 100644 --- a/test/PCH/ocl_types.h +++ b/test/PCH/ocl_types.h @@ -44,6 +44,7 @@ typedef image2d_depth_t img2ddep_t; // image2d_array_depth_t typedef image2d_array_depth_t img2darr_dep_t; +#pragma OPENCL EXTENSION cl_khr_gl_msaa_sharing : enable // image2d_msaa_t typedef image2d_msaa_t img2dmsaa_t; @@ -56,4 +57,14 @@ typedef image2d_msaa_depth_t img2dmsaadep_t; // image2d_array_msaa_depth_t typedef image2d_array_msaa_depth_t img2darrmsaadep_t; +// pipe specifier + +typedef struct _person { + int id; + const char *name; +} Person; + +void int_pipe_function(pipe int); + +void person_pipe_function(pipe Person); #endif diff --git a/test/Sema/bitfield-layout.c b/test/Sema/bitfield-layout.c index 2abd139d238f..b96b38686417 100644 --- a/test/Sema/bitfield-layout.c +++ b/test/Sema/bitfield-layout.c @@ -1,13 +1,25 @@ // RUN: %clang_cc1 %s -fsyntax-only -verify -triple=i686-apple-darwin9 +// RUN: %clang_cc1 %s -fsyntax-only -verify -triple=arm-linux-gnueabihf +// RUN: %clang_cc1 %s -fsyntax-only -verify -triple=aarch64-linux-gnu // expected-no-diagnostics +#include -#define CHECK_SIZE(kind, name, size) extern int name##1[sizeof(kind name) == size ? 1 : -1]; -#define CHECK_ALIGN(kind, name, size) extern int name##2[__alignof(kind name) == size ? 1 : -1]; +#define CHECK_SIZE(kind, name, size) \ + extern int name##_1[sizeof(kind name) == size ? 1 : -1]; +#define CHECK_ALIGN(kind, name, size) \ + extern int name##_2[__alignof(kind name) == size ? 1 : -1]; +#define CHECK_OFFSET(kind, name, member, offset) \ + extern int name##_3[offsetof(kind name, member) == offset ? 1 : -1]; // Zero-width bit-fields struct a {char x; int : 0; char y;}; +#if defined(__arm__) || defined(__aarch64__) +CHECK_SIZE(struct, a, 8) +CHECK_ALIGN(struct, a, 4) +#else CHECK_SIZE(struct, a, 5) CHECK_ALIGN(struct, a, 1) +#endif // Zero-width bit-fields with packed struct __attribute__((packed)) a2 { short x : 9; char : 0; int y : 17; }; @@ -16,8 +28,13 @@ CHECK_ALIGN(struct, a2, 1) // Zero-width bit-fields at the end of packed struct struct __attribute__((packed)) a3 { short x : 9; int : 0; }; +#if defined(__arm__) || defined(__aarch64__) +CHECK_SIZE(struct, a3, 4) +CHECK_ALIGN(struct, a3, 4) +#else CHECK_SIZE(struct, a3, 4) CHECK_ALIGN(struct, a3, 1) +#endif // For comparison, non-zero-width bit-fields at the end of packed struct struct __attribute__((packed)) a4 { short x : 9; int : 1; }; @@ -25,17 +42,32 @@ CHECK_SIZE(struct, a4, 2) CHECK_ALIGN(struct, a4, 1) union b {char x; int : 0; char y;}; +#if defined(__arm__) || defined(__aarch64__) +CHECK_SIZE(union, b, 4) +CHECK_ALIGN(union, b, 4) +#else CHECK_SIZE(union, b, 1) CHECK_ALIGN(union, b, 1) +#endif // Unnamed bit-field align struct c {char x; int : 20;}; +#if defined(__arm__) || defined(__aarch64__) +CHECK_SIZE(struct, c, 4) +CHECK_ALIGN(struct, c, 4) +#else CHECK_SIZE(struct, c, 4) CHECK_ALIGN(struct, c, 1) +#endif union d {char x; int : 20;}; +#if defined(__arm__) || defined(__aarch64__) +CHECK_SIZE(union, d, 4) +CHECK_ALIGN(union, d, 4) +#else CHECK_SIZE(union, d, 3) CHECK_ALIGN(union, d, 1) +#endif // Bit-field packing struct __attribute__((packed)) e {int x : 4, y : 30, z : 30;}; @@ -56,3 +88,153 @@ struct s0 { CHECK_SIZE(struct, s0, 0x32100008) CHECK_ALIGN(struct, s0, 4) +// Bit-field with explicit align bigger than normal. +struct g0 { + char a; + __attribute__((aligned(16))) int b : 1; + char c; +}; + +CHECK_SIZE(struct, g0, 32); +CHECK_ALIGN(struct, g0, 16); +CHECK_OFFSET(struct, g0, c, 17); + +// Bit-field with explicit align smaller than normal. +struct g1 { + char a; + __attribute__((aligned(2))) int b : 1; + char c; +}; + +CHECK_SIZE(struct, g1, 4); +CHECK_ALIGN(struct, g1, 4); +CHECK_OFFSET(struct, g1, c, 3); + +// Same as above but without explicit align. +struct g2 { + char a; + int b : 1; + char c; +}; + +CHECK_SIZE(struct, g2, 4); +CHECK_ALIGN(struct, g2, 4); +CHECK_OFFSET(struct, g2, c, 2); + +// Explicit attribute align on bit-field has precedence over packed attribute +// applied too the struct. +struct __attribute__((packed)) g3 { + char a; + __attribute__((aligned(16))) int b : 1; + char c; +}; + +CHECK_SIZE(struct, g3, 32); +CHECK_ALIGN(struct, g3, 16); +CHECK_OFFSET(struct, g3, c, 17); + +struct __attribute__((packed)) g4 { + char a; + __attribute__((aligned(2))) int b : 1; + char c; +}; + +CHECK_SIZE(struct, g4, 4); +CHECK_ALIGN(struct, g4, 2); +CHECK_OFFSET(struct, g4, c, 3); + +struct g5 { + char : 1; + __attribute__((aligned(1))) int n : 24; +}; +CHECK_SIZE(struct, g5, 4); +CHECK_ALIGN(struct, g5, 4); + +struct __attribute__((packed)) g6 { + char : 1; + __attribute__((aligned(1))) int n : 24; +}; +CHECK_SIZE(struct, g6, 4); +CHECK_ALIGN(struct, g6, 1); + +struct g7 { + char : 1; + __attribute__((aligned(1))) int n : 25; +}; +CHECK_SIZE(struct, g7, 8); +CHECK_ALIGN(struct, g7, 4); + +struct __attribute__((packed)) g8 { + char : 1; + __attribute__((aligned(1))) int n : 25; +}; +CHECK_SIZE(struct, g8, 5); +CHECK_ALIGN(struct, g8, 1); + +struct g9 { + __attribute__((aligned(1))) char a : 2, b : 2, c : 2, d : 2, e : 2; + int i; +}; +CHECK_SIZE(struct, g9, 12); +CHECK_ALIGN(struct, g9, 4); + +struct __attribute__((packed)) g10 { + __attribute__((aligned(1))) char a : 2, b : 2, c : 2, d : 2, e : 2; + int i; +}; +CHECK_SIZE(struct, g10, 9); +CHECK_ALIGN(struct, g10, 1); + +struct g11 { + char a; + __attribute__((aligned(1))) long long b : 62; + char c; +}; +#if defined(__arm__) || defined(__aarch64__) +CHECK_SIZE(struct, g11, 24); +CHECK_ALIGN(struct, g11, 8); +CHECK_OFFSET(struct, g11, c, 16); +#else +CHECK_SIZE(struct, g11, 16); +CHECK_ALIGN(struct, g11, 4); +CHECK_OFFSET(struct, g11, c, 12); +#endif + +struct __attribute__((packed)) g12 { + char a; + __attribute__((aligned(1))) long long b : 62; + char c; +}; +CHECK_SIZE(struct, g12, 10); +CHECK_ALIGN(struct, g12, 1); +CHECK_OFFSET(struct, g12, c, 9); + +struct g13 { + char a; + __attribute__((aligned(1))) long long : 0; + char c; +}; +#if defined(__arm__) || defined(__aarch64__) +CHECK_SIZE(struct, g13, 16); +CHECK_ALIGN(struct, g13, 8); +CHECK_OFFSET(struct, g13, c, 8); +#else +CHECK_SIZE(struct, g13, 5); +CHECK_ALIGN(struct, g13, 1); +CHECK_OFFSET(struct, g13, c, 4); +#endif + +struct __attribute__((packed)) g14 { + char a; + __attribute__((aligned(1))) long long : 0; + char c; +}; +#if defined(__arm__) || defined(__aarch64__) +CHECK_SIZE(struct, g14, 16); +CHECK_ALIGN(struct, g14, 8); +CHECK_OFFSET(struct, g14, c, 8); +#else +CHECK_SIZE(struct, g14, 5); +CHECK_ALIGN(struct, g14, 1); +CHECK_OFFSET(struct, g14, c, 4); +#endif diff --git a/test/Sema/darwin-tls.c b/test/Sema/darwin-tls.c new file mode 100644 index 000000000000..0fcf096d92ba --- /dev/null +++ b/test/Sema/darwin-tls.c @@ -0,0 +1,17 @@ +// RUN: not %clang_cc1 -fsyntax-only -triple x86_64-apple-macosx10.6 %s 2>&1 | FileCheck %s --check-prefix NO-TLS +// RUN: %clang_cc1 -fsyntax-only -triple x86_64-apple-macosx10.7 %s 2>&1 | FileCheck %s --check-prefix TLS +// RUN: not %clang_cc1 -fsyntax-only -triple arm64-apple-ios7.1 %s 2>&1 | FileCheck %s --check-prefix NO-TLS +// RUN: %clang_cc1 -fsyntax-only -triple arm64-apple-ios8.0 %s 2>&1 | FileCheck %s --check-prefix TLS +// RUN: not %clang_cc1 -fsyntax-only -triple thumbv7s-apple-ios8.3 %s 2>&1 | FileCheck %s --check-prefix NO-TLS +// RUN: %clang_cc1 -fsyntax-only -triple thumbv7s-apple-ios9.0 %s 2>&1 | FileCheck %s --check-prefix TLS +// RUN: %clang_cc1 -fsyntax-only -triple armv7-apple-ios9.0 %s 2>&1 | FileCheck %s --check-prefix TLS +// RUN: not %clang_cc1 -fsyntax-only -triple thumbv7k-apple-watchos1.0 %s 2>&1 | FileCheck %s --check-prefix NO-TLS +// RUN: %clang_cc1 -fsyntax-only -triple thumbv7k-apple-watchos2.0 %s 2>&1 | FileCheck %s --check-prefix TLS + + +__thread int a; + +// NO-TLS: thread-local storage is not supported for the current target +// TLS-NOT: thread-local storage is not supported for the current target + +wibble; diff --git a/test/Sema/decl-in-prototype.c b/test/Sema/decl-in-prototype.c index 4f581aa54e53..3b8a3b860371 100644 --- a/test/Sema/decl-in-prototype.c +++ b/test/Sema/decl-in-prototype.c @@ -35,3 +35,6 @@ void f6(struct z {int b;} c) { // expected-warning {{declaration of 'struct z' w void pr19018_1 (enum e19018 { qq } x); // expected-warning{{declaration of 'enum e19018' will not be visible outside of this function}} enum e19018 qq; //expected-error{{tentative definition has type 'enum e19018' that is never completed}} \ //expected-note{{forward declaration of 'enum e19018'}} + +// Only warn once, even if we create two declarations. +void f(struct q *, struct __attribute__((aligned(4))) q *); // expected-warning {{will not be visible outside}} diff --git a/test/Sema/integer-overflow.c b/test/Sema/integer-overflow.c index 44fbcd4c818e..db5c1f4c7118 100644 --- a/test/Sema/integer-overflow.c +++ b/test/Sema/integer-overflow.c @@ -145,3 +145,11 @@ uint64_t check_integer_overflows(int i) { // expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}} return ((4608 * 1024 * 1024) + ((uint64_t)(4608 * 1024 * 1024))); } + +struct s { + unsigned x; + unsigned y; +} s = { + .y = 5, + .x = 4 * 1024 * 1024 * 1024 // expected-warning {{overflow in expression; result is 0 with type 'int'}} +}; diff --git a/test/Sema/pass-object-size.c b/test/Sema/pass-object-size.c index e4f460b1785f..6f375c0e94d5 100644 --- a/test/Sema/pass-object-size.c +++ b/test/Sema/pass-object-size.c @@ -33,7 +33,7 @@ void TakeFnOvl(void (*)(int *)) overloaded; void NotOverloaded(void *p PS(0)); void IsOverloaded(void *p PS(0)) overloaded; -void IsOverloaded(char *p) overloaded; +void IsOverloaded(char *p) overloaded; // char* inestead of void* is intentional void FunctionPtrs() { void (*p)(void *) = NotOverloaded; //expected-error{{cannot take address of function 'NotOverloaded' because parameter 1 has pass_object_size attribute}} void (*p2)(void *) = &NotOverloaded; //expected-error{{cannot take address of function 'NotOverloaded' because parameter 1 has pass_object_size attribute}} @@ -49,4 +49,8 @@ void FunctionPtrs() { TakeFnOvl(NotOverloaded); //expected-error{{cannot take address of function 'NotOverloaded' because parameter 1 has pass_object_size attribute}} TakeFnOvl(&NotOverloaded); //expected-error{{cannot take address of function 'NotOverloaded' because parameter 1 has pass_object_size attribute}} + + int P; + (&NotOverloaded)(&P); //expected-error{{cannot take address of function 'NotOverloaded' because parameter 1 has pass_object_size attribute}} + (&IsOverloaded)(&P); //expected-error{{no matching function}} expected-note@35{{candidate address cannot be taken because parameter 1 has pass_object_size attribute}} expected-note@36{{candidate function not viable: no known conversion from 'int *' to 'char *' for 1st argument}} } diff --git a/test/SemaCUDA/Inputs/cuda.h b/test/SemaCUDA/Inputs/cuda.h index a9a4595a14a9..18cafdf96af8 100644 --- a/test/SemaCUDA/Inputs/cuda.h +++ b/test/SemaCUDA/Inputs/cuda.h @@ -2,6 +2,9 @@ #include +// Make this file work with nvcc, for testing compatibility. + +#ifndef __NVCC__ #define __constant__ __attribute__((constant)) #define __device__ __attribute__((device)) #define __global__ __attribute__((global)) @@ -18,3 +21,4 @@ typedef struct cudaStream *cudaStream_t; int cudaConfigureCall(dim3 gridSize, dim3 blockSize, size_t sharedSize = 0, cudaStream_t stream = 0); +#endif // !__NVCC__ diff --git a/test/SemaCUDA/attributes-on-non-cuda.cu b/test/SemaCUDA/attributes-on-non-cuda.cu new file mode 100644 index 000000000000..e9e32ce658cb --- /dev/null +++ b/test/SemaCUDA/attributes-on-non-cuda.cu @@ -0,0 +1,34 @@ +// Tests that CUDA attributes are warnings when compiling C files, but not when +// compiling CUDA files. +// +// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -fcuda-is-device -verify %s +// Now pretend that we're compiling a C file. There should be warnings. +// RUN: %clang_cc1 -DEXPECT_WARNINGS -fsyntax-only -verify -x c %s + +#if defined(EXPECT_WARNINGS) +// expected-warning@+12 {{'device' attribute ignored}} +// expected-warning@+12 {{'global' attribute ignored}} +// expected-warning@+12 {{'constant' attribute ignored}} +// expected-warning@+12 {{'shared' attribute ignored}} +// expected-warning@+12 {{'host' attribute ignored}} +// +// NOTE: IgnoredAttr in clang which is used for the rest of +// attributes ignores LangOpts, so there are no warnings. +#else +// expected-no-diagnostics +#endif + +__attribute__((device)) void f_device(); +__attribute__((global)) void f_global(); +__attribute__((constant)) int* g_constant; +__attribute__((shared)) float *g_shared; +__attribute__((host)) void f_host(); +__attribute__((device_builtin)) void f_device_builtin(); +typedef __attribute__((device_builtin)) const void *t_device_builtin; +enum __attribute__((device_builtin)) e_device_builtin {E}; +__attribute__((device_builtin)) int v_device_builtin; +__attribute__((cudart_builtin)) void f_cudart_builtin(); +__attribute__((nv_weak)) void f_nv_weak(); +__attribute__((device_builtin_surface_type)) unsigned long long surface_var; +__attribute__((device_builtin_texture_type)) unsigned long long texture_var; diff --git a/test/SemaCUDA/attributes.cu b/test/SemaCUDA/attributes.cu deleted file mode 100644 index ce4dc925a3f3..000000000000 --- a/test/SemaCUDA/attributes.cu +++ /dev/null @@ -1,33 +0,0 @@ -// Tests handling of CUDA attributes. -// -// RUN: %clang_cc1 -fsyntax-only -verify %s -// RUN: %clang_cc1 -fsyntax-only -fcuda-is-device -verify %s -// Now pretend that we're compiling a C file. There should be warnings. -// RUN: %clang_cc1 -DEXPECT_WARNINGS -fsyntax-only -verify -x c %s - -#if defined(EXPECT_WARNINGS) -// expected-warning@+12 {{'device' attribute ignored}} -// expected-warning@+12 {{'global' attribute ignored}} -// expected-warning@+12 {{'constant' attribute ignored}} -// expected-warning@+12 {{'shared' attribute ignored}} -// expected-warning@+12 {{'host' attribute ignored}} -// -// NOTE: IgnoredAttr in clang which is used for the rest of -// attributes ignores LangOpts, so there are no warnings. -#else -// expected-no-diagnostics -#endif - -__attribute__((device)) void f_device(); -__attribute__((global)) void f_global(); -__attribute__((constant)) int* g_constant; -__attribute__((shared)) float *g_shared; -__attribute__((host)) void f_host(); -__attribute__((device_builtin)) void f_device_builtin(); -typedef __attribute__((device_builtin)) const void *t_device_builtin; -enum __attribute__((device_builtin)) e_device_builtin {E}; -__attribute__((device_builtin)) int v_device_builtin; -__attribute__((cudart_builtin)) void f_cudart_builtin(); -__attribute__((nv_weak)) void f_nv_weak(); -__attribute__((device_builtin_surface_type)) unsigned long long surface_var; -__attribute__((device_builtin_texture_type)) unsigned long long texture_var; diff --git a/test/SemaCUDA/bad-attributes.cu b/test/SemaCUDA/bad-attributes.cu new file mode 100644 index 000000000000..7e01e141de1d --- /dev/null +++ b/test/SemaCUDA/bad-attributes.cu @@ -0,0 +1,49 @@ +// Tests handling of CUDA attributes that are bad either because they're +// applied to the wrong sort of thing, or because they're given in illegal +// combinations. +// +// You should be able to run this file through nvcc for compatibility testing. +// +// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fcuda-is-device -fsyntax-only -verify %s + +#include "Inputs/cuda.h" + +// Try applying attributes to functions and variables. Some should generate +// warnings; others not. +__device__ int a1; +__device__ void a2(); +__host__ int b1; // expected-warning {{attribute only applies to functions}} +__host__ void b2(); +__constant__ int c1; +__constant__ void c2(); // expected-warning {{attribute only applies to variables}} +__shared__ int d1; +__shared__ void d2(); // expected-warning {{attribute only applies to variables}} +__global__ int e1; // expected-warning {{attribute only applies to functions}} +__global__ void e2(); + +// Try all pairs of attributes which can be present on a function or a +// variable. Check both orderings of the attributes, as that can matter in +// clang. +__device__ __host__ void z1(); +__device__ __constant__ int z2; +__device__ __shared__ int z3; +__device__ __global__ void z4(); // expected-error {{attributes are not compatible}} +// expected-note@-1 {{conflicting attribute is here}} + +__host__ __device__ void z5(); +__host__ __global__ void z6(); // expected-error {{attributes are not compatible}} +// expected-note@-1 {{conflicting attribute is here}} + +__constant__ __device__ int z7; +__constant__ __shared__ int z8; // expected-error {{attributes are not compatible}} +// expected-note@-1 {{conflicting attribute is here}} + +__shared__ __device__ int z9; +__shared__ __constant__ int z10; // expected-error {{attributes are not compatible}} +// expected-note@-1 {{conflicting attribute is here}} + +__global__ __device__ void z11(); // expected-error {{attributes are not compatible}} +// expected-note@-1 {{conflicting attribute is here}} +__global__ __host__ void z12(); // expected-error {{attributes are not compatible}} +// expected-note@-1 {{conflicting attribute is here}} diff --git a/test/SemaCXX/anonymous-union.cpp b/test/SemaCXX/anonymous-union.cpp index 3520245a03a8..0b654266f75f 100644 --- a/test/SemaCXX/anonymous-union.cpp +++ b/test/SemaCXX/anonymous-union.cpp @@ -62,11 +62,11 @@ void test_unqual_references(X x, const X xc) { struct Redecl { int x; // expected-note{{previous declaration is here}} - class y { }; + class y { }; // expected-note{{previous declaration is here}} union { int x; // expected-error{{member of anonymous union redeclares 'x'}} - float y; + float y; // expected-error{{member of anonymous union redeclares 'y'}} double z; // expected-note{{previous declaration is here}} double zz; // expected-note{{previous definition is here}} }; diff --git a/test/SemaCXX/conversion.cpp b/test/SemaCXX/conversion.cpp index b8f0e076a2bc..4c4089c6aae7 100644 --- a/test/SemaCXX/conversion.cpp +++ b/test/SemaCXX/conversion.cpp @@ -77,30 +77,8 @@ void test3() { // CHECK: note: expanded from macro 'FINIT' #define FINIT int a3 = NULL; FINIT // expected-warning {{implicit conversion of NULL constant to 'int'}} - - // we don't catch the case of #define FOO NULL ... int i = FOO; but that seems a bit narrow anyway - // and avoiding that helps us skip these cases: -#define NULL_COND(cond) ((cond) ? &a : NULL) - bool bl2 = NULL_COND(true); // don't warn on NULL conversion through the conditional operator across a macro boundary - if (NULL_COND(true)) - ; - while (NULL_COND(true)) - ; - for (; NULL_COND(true); ) - ; - do ; - while(NULL_COND(true)); - -#define NULL_WRAPPER NULL_COND(false) - if (NULL_WRAPPER) - ; - while (NULL_WRAPPER) - ; - for (; NULL_WRAPPER;) - ; - do - ; - while (NULL_WRAPPER); + // we don't catch the case of #define FOO NULL ... int i = FOO; but that + // seems a bit narrow anyway and avoiding that helps us skip other cases. int *ip = NULL; int (*fp)() = NULL; @@ -116,9 +94,9 @@ namespace test4 { // FIXME: We should warn for non-dependent args (only when the param type is also non-dependent) only once // not once for the template + once for every instantiation template - void tmpl(char c = NULL, // expected-warning 4 {{implicit conversion of NULL constant to 'char'}} + void tmpl(char c = NULL, // expected-warning 3 {{implicit conversion of NULL constant to 'char'}} T a = NULL, // expected-warning {{implicit conversion of NULL constant to 'char'}} \ - expected-warning 2 {{implicit conversion of NULL constant to 'int'}} + expected-warning {{implicit conversion of NULL constant to 'int'}} T b = 1024) { // expected-warning {{implicit conversion from 'int' to 'char' changes value from 1024 to 0}} } @@ -129,8 +107,7 @@ namespace test4 { void func() { tmpl(); // expected-note 2 {{in instantiation of default function argument expression for 'tmpl' required here}} tmpl(); // expected-note 2 {{in instantiation of default function argument expression for 'tmpl' required here}} - // FIXME: We should warn only once for each template instantiation - not once for each call - tmpl(); // expected-note 2 {{in instantiation of default function argument expression for 'tmpl' required here}} + tmpl(); tmpl2(); } } @@ -157,3 +134,97 @@ namespace test7 { return nullptr; // expected-warning {{implicit conversion of nullptr constant to 'bool'}} } } + +namespace test8 { + #define NULL_COND(cond) ((cond) ? &num : NULL) + #define NULL_WRAPPER NULL_COND(false) + + // don't warn on NULL conversion through the conditional operator across a + // macro boundary + void macro() { + int num; + bool b = NULL_COND(true); + if (NULL_COND(true)) {} + while (NULL_COND(true)) {} + for (;NULL_COND(true);) {} + do {} while (NULL_COND(true)); + + if (NULL_WRAPPER) {} + while (NULL_WRAPPER) {} + for (;NULL_WRAPPER;) {} + do {} while (NULL_WRAPPER); + } + + // Identical to the previous function except with a template argument. + // This ensures that template instantiation does not introduce any new + // warnings. + template + void template_and_macro() { + int num; + bool b = NULL_COND(true); + if (NULL_COND(true)) {} + while (NULL_COND(true)) {} + for (;NULL_COND(true);) {} + do {} while (NULL_COND(true)); + + if (NULL_WRAPPER) {} + while (NULL_WRAPPER) {} + for (;NULL_WRAPPER;) {} + do {} while (NULL_WRAPPER); + } + + // Identical to the previous function except the template argument affects + // the conditional statement. + template + void template_and_macro2() { + X num; + bool b = NULL_COND(true); + if (NULL_COND(true)) {} + while (NULL_COND(true)) {} + for (;NULL_COND(true);) {} + do {} while (NULL_COND(true)); + + if (NULL_WRAPPER) {} + while (NULL_WRAPPER) {} + for (;NULL_WRAPPER;) {} + do {} while (NULL_WRAPPER); + } + + void run() { + template_and_macro(); + template_and_macro(); + template_and_macro2(); + template_and_macro2(); + } +} + +// Don't warn on a nullptr to bool conversion when the nullptr is the return +// type of a function. +namespace test9 { + typedef decltype(nullptr) nullptr_t; + nullptr_t EXIT(); + + bool test() { + return EXIT(); + } +} + +// Test NULL macro inside a macro has same warnings nullptr inside a macro. +namespace test10 { +#define test1(cond) \ + ((cond) ? nullptr : NULL) +#define test2(cond) \ + ((cond) ? NULL : nullptr) + +#define assert(cond) \ + ((cond) ? foo() : bar()) + void foo(); + void bar(); + + void run(int x) { + if (test1(x)) {} + if (test2(x)) {} + assert(test1(x)); + assert(test2(x)); + } +} diff --git a/test/SemaCXX/linkage-invalid-decl.cpp b/test/SemaCXX/linkage-invalid-decl.cpp new file mode 100644 index 000000000000..0a991baf9d7d --- /dev/null +++ b/test/SemaCXX/linkage-invalid-decl.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// This invalid declaration used to call infinite recursion in linkage +// calculation for enum as a function argument. +inline foo(A)(enum E; +// expected-error@-1 {{unknown type name 'foo'}} +// expected-error@-2 {{ISO C++ forbids forward references to 'enum' types}} +// expected-error@-3 {{expected ')'}} +// expected-note@-4 {{to match this '('}} diff --git a/test/SemaCXX/pass-object-size.cpp b/test/SemaCXX/pass-object-size.cpp index bec0c1c55f29..94c9cc9c8aa0 100644 --- a/test/SemaCXX/pass-object-size.cpp +++ b/test/SemaCXX/pass-object-size.cpp @@ -120,3 +120,17 @@ void Bar() { (void)+[](void *const p __attribute__((pass_object_size(0)))) {}; //expected-error-re{{invalid argument type '(lambda at {{.*}})' to unary expression}} } } + +namespace ovlbug { +// Directly calling an address-of function expression (e.g. in (&foo)(args...)) +// doesn't go through regular address-of-overload logic. This caused the above +// code to generate an ICE. +void DirectAddrOf(void *__attribute__((pass_object_size(0)))); +void DirectAddrOfOvl(void *__attribute__((pass_object_size(0)))); +void DirectAddrOfOvl(int *); + +void Test() { + (&DirectAddrOf)(nullptr); //expected-error{{cannot take address of function 'DirectAddrOf' because parameter 1 has pass_object_size attribute}} + (&DirectAddrOfOvl)((char*)nullptr); //expected-error{{no matching function}} expected-note@129{{candidate address cannot be taken because parameter 1 has pass_object_size attribute}} expected-note@130{{candidate function not viable: no known conversion from 'char *' to 'int *' for 1st argument}} +} +} diff --git a/test/SemaOpenCL/invalid-pipes-cl2.0.cl b/test/SemaOpenCL/invalid-pipes-cl2.0.cl new file mode 100644 index 000000000000..ee36892b93d4 --- /dev/null +++ b/test/SemaOpenCL/invalid-pipes-cl2.0.cl @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL2.0 + +void test1(pipe int *p){// expected-error {{pipes packet types cannot be of reference type}} +} +void test2(pipe p){// expected-error {{missing actual type specifier for pipe}} +} +void test3(int pipe p){// expected-error {{cannot combine with previous 'int' declaration specifier}} +} diff --git a/test/SemaOpenCL/pipes-1.2-negative.cl b/test/SemaOpenCL/pipes-1.2-negative.cl new file mode 100644 index 000000000000..441a24cf8522 --- /dev/null +++ b/test/SemaOpenCL/pipes-1.2-negative.cl @@ -0,0 +1,3 @@ +// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL1.2 + +void foo(read_only pipe int p); // expected-error {{expected parameter declarator}} expected-error {{expected ')'}} expected-note {{to match this '('}} diff --git a/test/SemaTemplate/default-arguments-cxx0x.cpp b/test/SemaTemplate/default-arguments-cxx0x.cpp index 4cfd7a5843f0..0c97c2056b75 100644 --- a/test/SemaTemplate/default-arguments-cxx0x.cpp +++ b/test/SemaTemplate/default-arguments-cxx0x.cpp @@ -56,3 +56,22 @@ namespace PR16975 { baz data{0}; } + +// rdar://23810407 +// An IRGen failure due to a symbol collision due to a default argument +// being instantiated twice. Credit goes to Richard Smith for this +// reduction to a -fsyntax-only failure. +namespace rdar23810407 { + // Instantiating the default argument multiple times will produce two + // different lambda types and thus instantiate this function multiple + // times, which will produce conflicting extern variable declarations. + template int f(T t) { + extern T rdar23810407_variable; + return 0; + } + template int g(int a = f([] {})); + void test() { + g(); + g(); + } +} diff --git a/test/SemaTemplate/temp_arg_template.cpp b/test/SemaTemplate/temp_arg_template.cpp index 4a0ed05d8799..6d93f1504a46 100644 --- a/test/SemaTemplate/temp_arg_template.cpp +++ b/test/SemaTemplate/temp_arg_template.cpp @@ -75,7 +75,11 @@ template