diff --git a/CMakeLists.txt b/CMakeLists.txt index 2c54e751e91..ad2ac42c403 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -631,11 +631,19 @@ if (CLANG_ENABLE_BOOTSTRAP) string(REGEX MATCH "stage([0-9]*)" MATCHED_STAGE "${CLANG_STAGE}") if(MATCHED_STAGE) - math(EXPR STAGE_NUM "${MATCHED_STAGE} + 1") - set(NEXT_CLANG_STAGE stage${STAGE_NUM}) + if(NOT LLVM_BUILD_INSTRUMENTED) + math(EXPR STAGE_NUM "${CMAKE_MATCH_1} + 1") + set(NEXT_CLANG_STAGE stage${STAGE_NUM}) + else() + set(NEXT_CLANG_STAGE stage${CMAKE_MATCH_1}) + endif() else() set(NEXT_CLANG_STAGE bootstrap) endif() + + if(BOOTSTRAP_LLVM_BUILD_INSTRUMENTED) + set(NEXT_CLANG_STAGE ${NEXT_CLANG_STAGE}-instrumented) + endif() message(STATUS "Setting next clang stage to: ${NEXT_CLANG_STAGE}") @@ -681,6 +689,26 @@ if (CLANG_ENABLE_BOOTSTRAP) set(RUNTIME_DEP compiler-rt) endif() + set(COMPILER_OPTIONS + -DCMAKE_CXX_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/clang++ + -DCMAKE_C_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/clang + -DCMAKE_ASM_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/clang) + + if(BOOTSTRAP_LLVM_BUILD_INSTRUMENTED) + set(PGO_DEP llvm-profdata) + set(PGO_OPT -DLLVM_PROFDATA=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-profdata) + endif() + + if(LLVM_BUILD_INSTRUMENTED) + set(PGO_DEP generate-profdata) + set(PGO_OPT -DLLVM_PROFDATA_FILE=${CMAKE_CURRENT_BINARY_DIR}/utils/perf-training/clang.profdata) + set(COMPILER_OPTIONS + -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} + -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} + -DCMAKE_ASM_COMPILER=${CMAKE_ASM_COMPILER}) + set(RUNTIME_DEP) # Don't set runtime dependencies + endif() + # Find all variables that start with BOOTSTRAP_ and populate a variable with # them. get_cmake_property(variableNames VARIABLES) @@ -703,7 +731,7 @@ if (CLANG_ENABLE_BOOTSTRAP) endforeach() ExternalProject_Add(${NEXT_CLANG_STAGE} - DEPENDS clang ${LTO_DEP} ${RUNTIME_DEP} + DEPENDS clang ${LTO_DEP} ${RUNTIME_DEP} ${PGO_DEP} PREFIX ${NEXT_CLANG_STAGE} SOURCE_DIR ${CMAKE_SOURCE_DIR} STAMP_DIR ${STAMP_DIR} @@ -715,11 +743,9 @@ if (CLANG_ENABLE_BOOTSTRAP) -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} ${CLANG_BOOTSTRAP_CMAKE_ARGS} ${PASSTHROUGH_VARIABLES} - -DCMAKE_CXX_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/clang++ - -DCMAKE_C_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/clang - -DCMAKE_ASM_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/clang - -DCLANG_STAGE=${NEXT_CLANG_STAGE} - ${LTO_LIBRARY} ${LTO_AR} ${LTO_RANLIB} ${verbose} + -DCLANG_STAGE=${NEXT_CLANG_STAGE} + ${COMPILER_OPTIONS} + ${LTO_LIBRARY} ${LTO_AR} ${LTO_RANLIB} ${verbose} ${PGO_OPT} INSTALL_COMMAND "" STEP_TARGETS configure build ${cmake_3_4_USES_TERMINAL_OPTIONS} diff --git a/cmake/caches/PGO-stage2-instrumented.cmake b/cmake/caches/PGO-stage2-instrumented.cmake new file mode 100644 index 00000000000..fe5e83d28a2 --- /dev/null +++ b/cmake/caches/PGO-stage2-instrumented.cmake @@ -0,0 +1,9 @@ +set(CMAKE_BUILD_TYPE RELEASE CACHE STRING "") +set(CLANG_ENABLE_BOOTSTRAP ON CACHE BOOL "") +set(LLVM_BUILD_EXTERNAL_COMPILER_RT ON CACHE BOOL "") + +set(CLANG_BOOTSTRAP_TARGETS check-all check-llvm check-clang test-suite CACHE STRING "") + +set(CLANG_BOOTSTRAP_CMAKE_ARGS + -C ${CMAKE_CURRENT_LIST_DIR}/PGO-stage2.cmake + CACHE STRING "") diff --git a/cmake/caches/PGO-stage2.cmake b/cmake/caches/PGO-stage2.cmake new file mode 100644 index 00000000000..2080cd405f2 --- /dev/null +++ b/cmake/caches/PGO-stage2.cmake @@ -0,0 +1,2 @@ +set(CMAKE_BUILD_TYPE RELEASE CACHE STRING "") +set(LLVM_BUILD_EXTERNAL_COMPILER_RT ON CACHE BOOL "") diff --git a/cmake/caches/PGO.cmake b/cmake/caches/PGO.cmake new file mode 100644 index 00000000000..dc11173fae3 --- /dev/null +++ b/cmake/caches/PGO.cmake @@ -0,0 +1,17 @@ +set(CMAKE_BUILD_TYPE RELEASE CACHE STRING "") +set(CLANG_ENABLE_BOOTSTRAP ON CACHE BOOL "") +set(LLVM_BUILD_EXTERNAL_COMPILER_RT ON CACHE BOOL "") + +set(LLVM_TARGETS_TO_BUILD X86 CACHE STRING "") +set(BOOTSTRAP_LLVM_BUILD_INSTRUMENTED ON CACHE BOOL "") +set(CLANG_BOOTSTRAP_TARGETS + generate-profdata + stage2 + stage2-check-all + stage2-check-llvm + stage2-check-clang + stage2-test-suite CACHE STRING "") + +set(CLANG_BOOTSTRAP_CMAKE_ARGS + -C ${CMAKE_CURRENT_LIST_DIR}/PGO-stage2-instrumented.cmake + CACHE STRING "") diff --git a/emscripten-version.txt b/emscripten-version.txt index 9c6893ff460..36f312da5a0 100644 --- a/emscripten-version.txt +++ b/emscripten-version.txt @@ -1,2 +1,2 @@ -"1.35.18" +"1.35.19" diff --git a/include/clang/AST/ASTMutationListener.h b/include/clang/AST/ASTMutationListener.h index 3ff392de11a..cf3b55d7b2c 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 @@ class ASTMutationListener { /// \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 85e237a2bf0..a08a6839024 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 046ce70a343..029c1182f26 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 05b2a1280fa..2d6e84a68aa 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -113,6 +113,9 @@ class Decl { /// 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 @@ class Decl { 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 @@ class Decl { /// 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 095dd6a1ef3..38733eee82c 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -1292,6 +1292,7 @@ class CharacterLiteral : public Expr { enum CharacterKind { Ascii, Wide, + UTF8, UTF16, UTF32 }; diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 0608abac1fe..68212749864 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -951,15 +951,9 @@ class CXXThrowExpr : public Expr { /// 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 @@ class CXXDefaultArgExpr final 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 @@ class CXXDefaultArgExpr final return child_range(child_iterator(), child_iterator()); } - friend TrailingObjects; friend class ASTStmtReader; friend class ASTStmtWriter; }; diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index e48b7dcc28f..d3950e92cf0 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -130,7 +130,7 @@ class LLVM_ALIGNAS(LLVM_PTR_SIZE) Stmt { friend class CharacterLiteral; unsigned : NumExprBits; - unsigned Kind : 2; + unsigned Kind : 3; }; enum APFloatSemantics { diff --git a/include/clang/Basic/Builtins.h b/include/clang/Basic/Builtins.h index 41f19e7cbfe..c0a6af9e262 100644 --- a/include/clang/Basic/Builtins.h +++ b/include/clang/Basic/Builtins.h @@ -192,6 +192,10 @@ class Context { /// for AuxTarget). unsigned getAuxBuiltinID(unsigned ID) const { return ID - TSRecords.size(); } + /// Returns true if this is a libc/libm function without the '__builtin_' + /// prefix. + static bool isBuiltinFunc(const char *Name); + private: const Info &getRecord(unsigned ID) const; diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td index 7a71285482f..ce270bfffc6 100644 --- a/include/clang/Basic/DiagnosticDriverKinds.td +++ b/include/clang/Basic/DiagnosticDriverKinds.td @@ -123,6 +123,9 @@ def err_drv_emit_llvm_link : Error< def err_drv_optimization_remark_pattern : Error< "%0 in '%1'">; def err_drv_no_neon_modifier : Error<"[no]neon is not accepted as modifier, please use [no]simd instead">; +def err_drv_invalid_omp_target : Error<"OpenMP target is invalid: '%0'">; +def err_drv_omp_host_ir_file_not_found : Error< + "The provided host compiler IR file '%0' is required to generate code for OpenMP target regions but cannot be found.">; def warn_O4_is_O3 : Warning<"-O4 is equivalent to -O3">, InGroup; def warn_drv_lto_libpath : Warning<"libLTO.dylib relative to clang installed dir not found; using 'ld' default search path instead">, diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 8e5f57d6d89..2e4e57b63b8 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 a675dfabe46..312b71f4064 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/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index 446852a86b0..f8dee2f98cc 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -910,6 +910,10 @@ def warn_pragma_expected_enable_disable : Warning< def warn_pragma_unknown_extension : Warning< "unknown OpenCL extension %0 - ignoring">, InGroup; +// OpenCL error +def err_opencl_taking_function_address_parser : Error< + "taking address of function is not allowed">; + // OpenMP support. def warn_pragma_omp_ignored : Warning< "unexpected '#pragma omp ...' in program">, InGroup, DefaultIgnore; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 59f5095d646..db8169531e2 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 diff --git a/include/clang/Basic/LangOptions.def b/include/clang/Basic/LangOptions.def index fdf7e49499b..cc70d6246c0 100644 --- a/include/clang/Basic/LangOptions.def +++ b/include/clang/Basic/LangOptions.def @@ -165,6 +165,8 @@ LANGOPT(HalfArgsAndReturns, 1, 0, "half args and returns") LANGOPT(CUDA , 1, 0, "CUDA") LANGOPT(OpenMP , 1, 0, "OpenMP support") LANGOPT(OpenMPUseTLS , 1, 0, "Use TLS for threadprivates or runtime calls") +LANGOPT(OpenMPIsDevice , 1, 0, "Generate code only for OpenMP target device") + LANGOPT(CUDAIsDevice , 1, 0, "Compiling for CUDA device") LANGOPT(CUDAAllowHostCallsFromHostDevice, 1, 0, "Allow host device functions to call host functions") LANGOPT(CUDADisableTargetCallChecks, 1, 0, "Disable checks for call targets (host, device, etc.)") diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h index 3c9d23efe63..736d4e0930b 100644 --- a/include/clang/Basic/LangOptions.h +++ b/include/clang/Basic/LangOptions.h @@ -108,7 +108,18 @@ class LangOptions : public LangOptionsBase { /// \brief Options for parsing comments. CommentOptions CommentOpts; - + + /// \brief A list of all -fno-builtin-* function names (e.g., memset). + std::vector NoBuiltinFuncs; + + /// \brief Triples of the OpenMP targets that the host code codegen should + /// take into account in order to generate accurate offloading descriptors. + std::vector OMPTargetTriples; + + /// \brief Name of the IR file that contains the result of the OpenMP target + /// host code generation. + std::string OMPHostIRFile; + LangOptions(); // Define accessors/mutators for language options of enumeration type. @@ -134,6 +145,10 @@ class LangOptions : public LangOptionsBase { /// \brief Reset all of the options that are not considered when building a /// module. void resetNonModularOptions(); + + /// \brief Is this a libc/libm function that is no longer recognized as a + /// builtin because a -fno-builtin-* option has been specified? + bool isNoBuiltinFunc(const char *Name) const; }; /// \brief Floating point control options diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index d7f42a991a8..051f9033756 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -677,6 +677,15 @@ def fcuda_include_gpubinary : Separate<["-"], "fcuda-include-gpubinary">, def fcuda_target_overloads : Flag<["-"], "fcuda-target-overloads">, HelpText<"Enable function overloads based on CUDA target attributes.">; +//===----------------------------------------------------------------------===// +// OpenMP Options +//===----------------------------------------------------------------------===// + +def fopenmp_is_device : Flag<["-"], "fopenmp-is-device">, + HelpText<"Generate code only for an OpenMP target device.">; +def omp_host_ir_file_path : Separate<["-"], "omp-host-ir-file-path">, + HelpText<"Path to the IR file produced by the frontend for the host.">; + } // let Flags = [CC1Option] diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 7eb4a46db88..e4279e80d84 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -814,7 +814,7 @@ def fno_blocks : Flag<["-"], "fno-blocks">, Group; def fno_borland_extensions : Flag<["-"], "fno-borland-extensions">, Group; def fno_builtin : Flag<["-"], "fno-builtin">, Group, Flags<[CC1Option]>, HelpText<"Disable implicit builtin knowledge of functions">; -def fno_builtin_ : Joined<["-"], "fno-builtin-">, Group, +def fno_builtin_ : Joined<["-"], "fno-builtin-">, Group, Flags<[CC1Option]>, HelpText<"Disable implicit builtin knowledge of a specific function">; def fno_math_builtin : Flag<["-"], "fno-math-builtin">, Group, Flags<[CC1Option]>, HelpText<"Disable implicit builtin knowledge of math functions">; @@ -1385,6 +1385,8 @@ def mno_restrict_it: Flag<["-"], "mno-restrict-it">, Group def marm : Flag<["-"], "marm">, Alias; def ffixed_r9 : Flag<["-"], "ffixed-r9">, Group, HelpText<"Reserve the r9 register (ARM only)">; +def mno_movt : Flag<["-"], "mno-movt">, Group, + HelpText<"Disallow use of movt/movw pairs (ARM only)">; def mcrc : Flag<["-"], "mcrc">, Group, HelpText<"Allow use of CRC instructions (ARM only)">; def mnocrc : Flag<["-"], "mnocrc">, Group, @@ -1649,6 +1651,8 @@ def nostdlib : Flag<["-"], "nostdlib">; def object : Flag<["-"], "object">; def o : JoinedOrSeparate<["-"], "o">, Flags<[DriverOption, RenderAsInput, CC1Option, CC1AsOption]>, HelpText<"Write output to ">, MetaVarName<"">; +def omptargets_EQ : CommaJoined<["-"], "omptargets=">, Flags<[DriverOption, CC1Option]>, + HelpText<"Specify comma-separated list of triples OpenMP offloading targets to be supported">; def pagezero__size : JoinedOrSeparate<["-"], "pagezero_size">; def pass_exit_codes : Flag<["-", "--"], "pass-exit-codes">, Flags<[Unsupported]>; def pedantic_errors : Flag<["-", "--"], "pedantic-errors">, Group, Flags<[CC1Option]>; @@ -1902,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 ed73107940c..7e68d0a59a0 100644 --- a/include/clang/Driver/ToolChain.h +++ b/include/clang/Driver/ToolChain.h @@ -134,7 +134,7 @@ class ToolChain { 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/Frontend/CodeGenOptions.h b/include/clang/Frontend/CodeGenOptions.h index fac6f1a038f..7550e6f4c74 100644 --- a/include/clang/Frontend/CodeGenOptions.h +++ b/include/clang/Frontend/CodeGenOptions.h @@ -218,6 +218,9 @@ class CodeGenOptions : public CodeGenOptionsBase { /// Set of sanitizer checks that trap rather than diagnose. SanitizerSet SanitizeTrap; + /// \brief A list of all -fno-builtin-* function names (e.g., memset). + std::vector NoBuiltinFuncs; + public: // Define accessors/mutators for code generation options of enumeration type. #define CODEGENOPT(Name, Bits, Default) @@ -227,6 +230,14 @@ class CodeGenOptions : public CodeGenOptionsBase { #include "clang/Frontend/CodeGenOptions.def" CodeGenOptions(); + + /// \brief Is this a libc/libm function that is no longer recognized as a + /// builtin because a -fno-builtin-* option has been specified? + bool isNoBuiltinFunc(const char *Name) const; + + const std::vector &getNoBuiltinFuncs() const { + return NoBuiltinFuncs; + } }; } // end namespace clang diff --git a/include/clang/Lex/LiteralSupport.h b/include/clang/Lex/LiteralSupport.h index 5210e3f2e1c..d568614e2ae 100644 --- a/include/clang/Lex/LiteralSupport.h +++ b/include/clang/Lex/LiteralSupport.h @@ -166,6 +166,7 @@ class CharLiteralParser { 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/Sema/Overload.h b/include/clang/Sema/Overload.h index 20958b057a4..62437953b35 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 bce2f0c0bad..279afbe740e 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -2548,7 +2548,8 @@ class Sema { 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, @@ -3416,7 +3417,6 @@ class Sema { bool LookupInlineAsmField(StringRef Base, StringRef Member, unsigned &Offset, SourceLocation AsmLoc); ExprResult LookupInlineAsmVarDeclField(Expr *RefExpr, StringRef Member, - unsigned &Offset, llvm::InlineAsmIdentifierInfo &Info, SourceLocation AsmLoc); StmtResult ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc, diff --git a/include/clang/Serialization/ASTWriter.h b/include/clang/Serialization/ASTWriter.h index ed345472fc7..ef8c6534138 100644 --- a/include/clang/Serialization/ASTWriter.h +++ b/include/clang/Serialization/ASTWriter.h @@ -871,6 +871,7 @@ class ASTWriter : public ASTDeserializationListener, 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/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 42bebc543e3..797e07b4b78 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -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 16394e865eb..72587e388e4 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/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index d35efcb101b..ea983340a29 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/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index e55b2fc19a1..69f52f52b66 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/Basic/Builtins.cpp b/lib/Basic/Builtins.cpp index 69b10c13ede..fb6a6451aa8 100644 --- a/lib/Basic/Builtins.cpp +++ b/lib/Basic/Builtins.cpp @@ -48,10 +48,20 @@ void Builtin::Context::InitializeTarget(const TargetInfo &Target, AuxTSRecords = AuxTarget->getTargetBuiltins(); } +bool Builtin::Context::isBuiltinFunc(const char *Name) { + StringRef FuncName(Name); + for (unsigned i = Builtin::NotBuiltin + 1; i != Builtin::FirstTSBuiltin; ++i) + if (FuncName.equals(BuiltinInfo[i].Name)) + return strchr(BuiltinInfo[i].Attributes, 'f') != nullptr; + + return false; +} + bool Builtin::Context::builtinIsSupported(const Builtin::Info &BuiltinInfo, const LangOptions &LangOpts) { - bool BuiltinsUnsupported = LangOpts.NoBuiltin && - strchr(BuiltinInfo.Attributes, 'f'); + bool BuiltinsUnsupported = + (LangOpts.NoBuiltin || LangOpts.isNoBuiltinFunc(BuiltinInfo.Name)) && + strchr(BuiltinInfo.Attributes, 'f'); bool MathBuiltinsUnsupported = LangOpts.NoMathBuiltin && BuiltinInfo.HeaderName && llvm::StringRef(BuiltinInfo.HeaderName).equals("math.h"); diff --git a/lib/Basic/LangOptions.cpp b/lib/Basic/LangOptions.cpp index 2c87845b7b0..1b08b068604 100644 --- a/lib/Basic/LangOptions.cpp +++ b/lib/Basic/LangOptions.cpp @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// #include "clang/Basic/LangOptions.h" +#include "llvm/ADT/StringRef.h" using namespace clang; @@ -36,3 +37,10 @@ void LangOptions::resetNonModularOptions() { ImplementationOfModule.clear(); } +bool LangOptions::isNoBuiltinFunc(const char *Name) const { + StringRef FuncName(Name); + for (unsigned i = 0, e = NoBuiltinFuncs.size(); i != e; ++i) + if (FuncName.equals(NoBuiltinFuncs[i])) + return true; + return false; +} diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp index f9ae0162271..b3ee329faf8 100644 --- a/lib/Basic/Targets.cpp +++ b/lib/Basic/Targets.cpp @@ -223,7 +223,24 @@ class DarwinTargetInfo : public OSTargetInfo { 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"; } @@ -5361,7 +5378,8 @@ class AArch64TargetInfo : public TargetInfo { bool setCPU(const std::string &Name) override { bool CPUKnown = llvm::StringSwitch(Name) .Case("generic", true) - .Cases("cortex-a53", "cortex-a57", "cortex-a72", "cortex-a35", true) + .Cases("cortex-a53", "cortex-a57", "cortex-a72", + "cortex-a35", "exynos-m1", true) .Case("cyclone", true) .Default(false); return CPUKnown; @@ -7383,7 +7401,7 @@ class WebAssembly32TargetInfo : public WebAssemblyTargetInfo { 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: @@ -7401,7 +7419,7 @@ class WebAssembly64TargetInfo : public WebAssemblyTargetInfo { 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/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp index 82297e7ee41..7032d00386f 100644 --- a/lib/CodeGen/BackendUtil.cpp +++ b/lib/CodeGen/BackendUtil.cpp @@ -249,6 +249,13 @@ static TargetLibraryInfoImpl *createTLII(llvm::Triple &TargetTriple, TargetLibraryInfoImpl *TLII = new TargetLibraryInfoImpl(TargetTriple); if (!CodeGenOpts.SimplifyLibCalls) TLII->disableAllFunctions(); + else { + // Disable individual libc/libm calls in TargetLibraryInfo. + LibFunc::Func F; + for (auto &FuncName : CodeGenOpts.getNoBuiltinFuncs()) + if (TLII->getLibFunc(FuncName, F)) + TLII->setUnavailable(F); + } switch (CodeGenOpts.getVecLib()) { case CodeGenOptions::Accelerate: diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index 49b5df0c4f0..935985049c0 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -1431,11 +1431,9 @@ static void AddAttributesFromFunctionProtoType(ASTContext &Ctx, FuncAttrs.addAttribute(llvm::Attribute::NoUnwind); } -void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI, - CGCalleeInfo CalleeInfo, - AttributeListType &PAL, - unsigned &CallingConv, - bool AttrOnCallSite) { +void CodeGenModule::ConstructAttributeList( + StringRef Name, const CGFunctionInfo &FI, CGCalleeInfo CalleeInfo, + AttributeListType &PAL, unsigned &CallingConv, bool AttrOnCallSite) { llvm::AttrBuilder FuncAttrs; llvm::AttrBuilder RetAttrs; bool HasOptnone = false; @@ -1510,7 +1508,8 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI, if (AttrOnCallSite) { // Attributes that should go on the call site only. - if (!CodeGenOpts.SimplifyLibCalls) + if (!CodeGenOpts.SimplifyLibCalls || + CodeGenOpts.isNoBuiltinFunc(Name.data())) FuncAttrs.addAttribute(llvm::Attribute::NoBuiltin); if (!CodeGenOpts.TrapFuncName.empty()) FuncAttrs.addAttribute("trap-func-name", CodeGenOpts.TrapFuncName); @@ -3490,8 +3489,9 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, unsigned CallingConv; CodeGen::AttributeListType AttributeList; - CGM.ConstructAttributeList(CallInfo, CalleeInfo, AttributeList, CallingConv, - true); + CGM.ConstructAttributeList(Callee->getName(), CallInfo, CalleeInfo, + AttributeList, CallingConv, + /*AttrOnCallSite=*/true); llvm::AttributeSet Attrs = llvm::AttributeSet::get(getLLVMContext(), AttributeList); diff --git a/lib/CodeGen/CGOpenMPRuntime.cpp b/lib/CodeGen/CGOpenMPRuntime.cpp index 0ba7e0639ac..6d4fc9f64b4 100644 --- a/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/lib/CodeGen/CGOpenMPRuntime.cpp @@ -11,16 +11,19 @@ // //===----------------------------------------------------------------------===// +#include "CGCXXABI.h" +#include "CGCleanup.h" #include "CGOpenMPRuntime.h" #include "CodeGenFunction.h" -#include "CGCleanup.h" #include "clang/AST/Decl.h" #include "clang/AST/StmtOpenMP.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/Bitcode/ReaderWriter.h" #include "llvm/IR/CallSite.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/GlobalValue.h" #include "llvm/IR/Value.h" +#include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" #include @@ -215,25 +218,31 @@ class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo { /// \brief API for captured statement code generation in OpenMP target /// constructs. For this captures, implicit parameters are used instead of the -/// captured fields. +/// captured fields. The name of the target region has to be unique in a given +/// application so it is provided by the client, because only the client has +/// the information to generate that. class CGOpenMPTargetRegionInfo : public CGOpenMPRegionInfo { public: CGOpenMPTargetRegionInfo(const CapturedStmt &CS, - const RegionCodeGenTy &CodeGen) + const RegionCodeGenTy &CodeGen, StringRef HelperName) : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target, - /*HasCancel = */ false) {} + /*HasCancel=*/false), + HelperName(HelperName) {} /// \brief This is unused for target regions because each starts executing /// with a single thread. const VarDecl *getThreadIDVariable() const override { return nullptr; } /// \brief Get the name of the capture helper. - StringRef getHelperName() const override { return ".omp_offloading."; } + StringRef getHelperName() const override { return HelperName; } static bool classof(const CGCapturedStmtInfo *Info) { return CGOpenMPRegionInfo::classof(Info) && cast(Info)->getRegionKind() == TargetRegion; } + +private: + StringRef HelperName; }; /// \brief RAII for emitting code of OpenMP constructs. @@ -301,7 +310,8 @@ LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue( } CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM) - : CGM(CGM), DefaultOpenMPPSource(nullptr), KmpRoutineEntryPtrTy(nullptr) { + : CGM(CGM), DefaultOpenMPPSource(nullptr), KmpRoutineEntryPtrTy(nullptr), + OffloadEntriesInfoManager(CGM) { IdentTy = llvm::StructType::create( "ident_t", CGM.Int32Ty /* reserved_1 */, CGM.Int32Ty /* flags */, CGM.Int32Ty /* reserved_2 */, CGM.Int32Ty /* reserved_3 */, @@ -311,6 +321,8 @@ CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM) llvm::PointerType::getUnqual(CGM.Int32Ty)}; Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true); KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8); + + loadOffloadInfoMetadata(); } void CGOpenMPRuntime::clear() { @@ -931,6 +943,26 @@ CGOpenMPRuntime::createRuntimeFunction(OpenMPRTLFunction Function) { RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target"); break; } + case OMPRTL__tgt_register_lib: { + // Build void __tgt_register_lib(__tgt_bin_desc *desc); + QualType ParamTy = + CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy()); + llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)}; + llvm::FunctionType *FnTy = + llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); + RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_lib"); + break; + } + case OMPRTL__tgt_unregister_lib: { + // Build void __tgt_unregister_lib(__tgt_bin_desc *desc); + QualType ParamTy = + CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy()); + llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)}; + llvm::FunctionType *FnTy = + llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); + RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_unregister_lib"); + break; + } } return RTLFn; } @@ -1969,6 +2001,381 @@ enum KmpTaskTFields { }; } // anonymous namespace +bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const { + // FIXME: Add other entries type when they become supported. + return OffloadEntriesTargetRegion.empty(); +} + +/// \brief Initialize target region entry. +void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: + initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, + StringRef ParentName, unsigned LineNum, + unsigned ColNum, unsigned Order) { + assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " + "only required for the device " + "code generation."); + OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum][ColNum] = + OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr); + ++OffloadingEntriesNum; +} + +void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: + registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, + StringRef ParentName, unsigned LineNum, + unsigned ColNum, llvm::Constant *Addr, + llvm::Constant *ID) { + // If we are emitting code for a target, the entry is already initialized, + // only has to be registered. + if (CGM.getLangOpts().OpenMPIsDevice) { + assert(hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum, + ColNum) && + "Entry must exist."); + auto &Entry = OffloadEntriesTargetRegion[DeviceID][FileID][ParentName] + [LineNum][ColNum]; + assert(Entry.isValid() && "Entry not initialized!"); + Entry.setAddress(Addr); + Entry.setID(ID); + return; + } else { + OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum++, Addr, ID); + OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum][ColNum] = + Entry; + } +} + +bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo( + unsigned DeviceID, unsigned FileID, StringRef ParentName, unsigned LineNum, + unsigned ColNum) const { + auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID); + if (PerDevice == OffloadEntriesTargetRegion.end()) + return false; + auto PerFile = PerDevice->second.find(FileID); + if (PerFile == PerDevice->second.end()) + return false; + auto PerParentName = PerFile->second.find(ParentName); + if (PerParentName == PerFile->second.end()) + return false; + auto PerLine = PerParentName->second.find(LineNum); + if (PerLine == PerParentName->second.end()) + return false; + auto PerColumn = PerLine->second.find(ColNum); + if (PerColumn == PerLine->second.end()) + return false; + // Fail if this entry is already registered. + if (PerColumn->second.getAddress() || PerColumn->second.getID()) + return false; + return true; +} + +void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo( + const OffloadTargetRegionEntryInfoActTy &Action) { + // Scan all target region entries and perform the provided action. + for (auto &D : OffloadEntriesTargetRegion) + for (auto &F : D.second) + for (auto &P : F.second) + for (auto &L : P.second) + for (auto &C : L.second) + Action(D.first, F.first, P.first(), L.first, C.first, C.second); +} + +/// \brief Create a Ctor/Dtor-like function whose body is emitted through +/// \a Codegen. This is used to emit the two functions that register and +/// unregister the descriptor of the current compilation unit. +static llvm::Function * +createOffloadingBinaryDescriptorFunction(CodeGenModule &CGM, StringRef Name, + const RegionCodeGenTy &Codegen) { + auto &C = CGM.getContext(); + FunctionArgList Args; + ImplicitParamDecl DummyPtr(C, /*DC=*/nullptr, SourceLocation(), + /*Id=*/nullptr, C.VoidPtrTy); + Args.push_back(&DummyPtr); + + CodeGenFunction CGF(CGM); + GlobalDecl(); + auto &FI = CGM.getTypes().arrangeFreeFunctionDeclaration( + C.VoidTy, Args, FunctionType::ExtInfo(), + /*isVariadic=*/false); + auto FTy = CGM.getTypes().GetFunctionType(FI); + auto *Fn = + CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, SourceLocation()); + CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FI, Args, SourceLocation()); + Codegen(CGF); + CGF.FinishFunction(); + return Fn; +} + +llvm::Function * +CGOpenMPRuntime::createOffloadingBinaryDescriptorRegistration() { + + // If we don't have entries or if we are emitting code for the device, we + // don't need to do anything. + if (CGM.getLangOpts().OpenMPIsDevice || OffloadEntriesInfoManager.empty()) + return nullptr; + + auto &M = CGM.getModule(); + auto &C = CGM.getContext(); + + // Get list of devices we care about + auto &Devices = CGM.getLangOpts().OMPTargetTriples; + + // We should be creating an offloading descriptor only if there are devices + // specified. + assert(!Devices.empty() && "No OpenMP offloading devices??"); + + // Create the external variables that will point to the begin and end of the + // host entries section. These will be defined by the linker. + auto *OffloadEntryTy = + CGM.getTypes().ConvertTypeForMem(getTgtOffloadEntryQTy()); + llvm::GlobalVariable *HostEntriesBegin = new llvm::GlobalVariable( + M, OffloadEntryTy, /*isConstant=*/true, + llvm::GlobalValue::ExternalLinkage, /*Initializer=*/0, + ".omp_offloading.entries_begin"); + llvm::GlobalVariable *HostEntriesEnd = new llvm::GlobalVariable( + M, OffloadEntryTy, /*isConstant=*/true, + llvm::GlobalValue::ExternalLinkage, /*Initializer=*/0, + ".omp_offloading.entries_end"); + + // Create all device images + llvm::SmallVector DeviceImagesEntires; + auto *DeviceImageTy = cast( + CGM.getTypes().ConvertTypeForMem(getTgtDeviceImageQTy())); + + for (unsigned i = 0; i < Devices.size(); ++i) { + StringRef T = Devices[i].getTriple(); + auto *ImgBegin = new llvm::GlobalVariable( + M, CGM.Int8Ty, /*isConstant=*/true, llvm::GlobalValue::ExternalLinkage, + /*Initializer=*/0, Twine(".omp_offloading.img_start.") + Twine(T)); + auto *ImgEnd = new llvm::GlobalVariable( + M, CGM.Int8Ty, /*isConstant=*/true, llvm::GlobalValue::ExternalLinkage, + /*Initializer=*/0, Twine(".omp_offloading.img_end.") + Twine(T)); + + llvm::Constant *Dev = + llvm::ConstantStruct::get(DeviceImageTy, ImgBegin, ImgEnd, + HostEntriesBegin, HostEntriesEnd, nullptr); + DeviceImagesEntires.push_back(Dev); + } + + // Create device images global array. + llvm::ArrayType *DeviceImagesInitTy = + llvm::ArrayType::get(DeviceImageTy, DeviceImagesEntires.size()); + llvm::Constant *DeviceImagesInit = + llvm::ConstantArray::get(DeviceImagesInitTy, DeviceImagesEntires); + + llvm::GlobalVariable *DeviceImages = new llvm::GlobalVariable( + M, DeviceImagesInitTy, /*isConstant=*/true, + llvm::GlobalValue::InternalLinkage, DeviceImagesInit, + ".omp_offloading.device_images"); + DeviceImages->setUnnamedAddr(true); + + // This is a Zero array to be used in the creation of the constant expressions + llvm::Constant *Index[] = {llvm::Constant::getNullValue(CGM.Int32Ty), + llvm::Constant::getNullValue(CGM.Int32Ty)}; + + // Create the target region descriptor. + auto *BinaryDescriptorTy = cast( + CGM.getTypes().ConvertTypeForMem(getTgtBinaryDescriptorQTy())); + llvm::Constant *TargetRegionsDescriptorInit = llvm::ConstantStruct::get( + BinaryDescriptorTy, llvm::ConstantInt::get(CGM.Int32Ty, Devices.size()), + llvm::ConstantExpr::getGetElementPtr(DeviceImagesInitTy, DeviceImages, + Index), + HostEntriesBegin, HostEntriesEnd, nullptr); + + auto *Desc = new llvm::GlobalVariable( + M, BinaryDescriptorTy, /*isConstant=*/true, + llvm::GlobalValue::InternalLinkage, TargetRegionsDescriptorInit, + ".omp_offloading.descriptor"); + + // Emit code to register or unregister the descriptor at execution + // startup or closing, respectively. + + // Create a variable to drive the registration and unregistration of the + // descriptor, so we can reuse the logic that emits Ctors and Dtors. + auto *IdentInfo = &C.Idents.get(".omp_offloading.reg_unreg_var"); + ImplicitParamDecl RegUnregVar(C, C.getTranslationUnitDecl(), SourceLocation(), + IdentInfo, C.CharTy); + + auto *UnRegFn = createOffloadingBinaryDescriptorFunction( + CGM, ".omp_offloading.descriptor_unreg", [&](CodeGenFunction &CGF) { + CGF.EmitCallOrInvoke(createRuntimeFunction(OMPRTL__tgt_unregister_lib), + Desc); + }); + auto *RegFn = createOffloadingBinaryDescriptorFunction( + CGM, ".omp_offloading.descriptor_reg", [&](CodeGenFunction &CGF) { + CGF.EmitCallOrInvoke(createRuntimeFunction(OMPRTL__tgt_register_lib), + Desc); + CGM.getCXXABI().registerGlobalDtor(CGF, RegUnregVar, UnRegFn, Desc); + }); + return RegFn; +} + +void CGOpenMPRuntime::createOffloadEntry(llvm::Constant *Addr, StringRef Name, + uint64_t Size) { + auto *TgtOffloadEntryType = cast( + CGM.getTypes().ConvertTypeForMem(getTgtOffloadEntryQTy())); + llvm::LLVMContext &C = CGM.getModule().getContext(); + llvm::Module &M = CGM.getModule(); + + // Make sure the address has the right type. + llvm::Constant *AddrPtr = llvm::ConstantExpr::getBitCast(Addr, CGM.VoidPtrTy); + + // Create constant string with the name. + llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name); + + llvm::GlobalVariable *Str = + new llvm::GlobalVariable(M, StrPtrInit->getType(), /*isConstant=*/true, + llvm::GlobalValue::InternalLinkage, StrPtrInit, + ".omp_offloading.entry_name"); + Str->setUnnamedAddr(true); + llvm::Constant *StrPtr = llvm::ConstantExpr::getBitCast(Str, CGM.Int8PtrTy); + + // Create the entry struct. + llvm::Constant *EntryInit = llvm::ConstantStruct::get( + TgtOffloadEntryType, AddrPtr, StrPtr, + llvm::ConstantInt::get(CGM.SizeTy, Size), nullptr); + llvm::GlobalVariable *Entry = new llvm::GlobalVariable( + M, TgtOffloadEntryType, true, llvm::GlobalValue::ExternalLinkage, + EntryInit, ".omp_offloading.entry"); + + // The entry has to be created in the section the linker expects it to be. + Entry->setSection(".omp_offloading.entries"); + // We can't have any padding between symbols, so we need to have 1-byte + // alignment. + Entry->setAlignment(1); + return; +} + +void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() { + // Emit the offloading entries and metadata so that the device codegen side + // can + // easily figure out what to emit. The produced metadata looks like this: + // + // !omp_offload.info = !{!1, ...} + // + // Right now we only generate metadata for function that contain target + // regions. + + // If we do not have entries, we dont need to do anything. + if (OffloadEntriesInfoManager.empty()) + return; + + llvm::Module &M = CGM.getModule(); + llvm::LLVMContext &C = M.getContext(); + SmallVector + OrderedEntries(OffloadEntriesInfoManager.size()); + + // Create the offloading info metadata node. + llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info"); + + // Auxiliar methods to create metadata values and strings. + auto getMDInt = [&](unsigned v) { + return llvm::ConstantAsMetadata::get( + llvm::ConstantInt::get(llvm::Type::getInt32Ty(C), v)); + }; + + auto getMDString = [&](StringRef v) { return llvm::MDString::get(C, v); }; + + // Create function that emits metadata for each target region entry; + auto &&TargetRegionMetadataEmitter = [&]( + unsigned DeviceID, unsigned FileID, StringRef ParentName, unsigned Line, + unsigned Column, + OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) { + llvm::SmallVector Ops; + // Generate metadata for target regions. Each entry of this metadata + // contains: + // - Entry 0 -> Kind of this type of metadata (0). + // - Entry 1 -> Device ID of the file where the entry was identified. + // - Entry 2 -> File ID of the file where the entry was identified. + // - Entry 3 -> Mangled name of the function where the entry was identified. + // - Entry 4 -> Line in the file where the entry was identified. + // - Entry 5 -> Column in the file where the entry was identified. + // - Entry 6 -> Order the entry was created. + // The first element of the metadata node is the kind. + Ops.push_back(getMDInt(E.getKind())); + Ops.push_back(getMDInt(DeviceID)); + Ops.push_back(getMDInt(FileID)); + Ops.push_back(getMDString(ParentName)); + Ops.push_back(getMDInt(Line)); + Ops.push_back(getMDInt(Column)); + Ops.push_back(getMDInt(E.getOrder())); + + // Save this entry in the right position of the ordered entries array. + OrderedEntries[E.getOrder()] = &E; + + // Add metadata to the named metadata node. + MD->addOperand(llvm::MDNode::get(C, Ops)); + }; + + OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo( + TargetRegionMetadataEmitter); + + for (auto *E : OrderedEntries) { + assert(E && "All ordered entries must exist!"); + if (auto *CE = + dyn_cast( + E)) { + assert(CE->getID() && CE->getAddress() && + "Entry ID and Addr are invalid!"); + createOffloadEntry(CE->getID(), CE->getAddress()->getName(), /*Size=*/0); + } else + llvm_unreachable("Unsupported entry kind."); + } +} + +/// \brief Loads all the offload entries information from the host IR +/// metadata. +void CGOpenMPRuntime::loadOffloadInfoMetadata() { + // If we are in target mode, load the metadata from the host IR. This code has + // to match the metadaata creation in createOffloadEntriesAndInfoMetadata(). + + if (!CGM.getLangOpts().OpenMPIsDevice) + return; + + if (CGM.getLangOpts().OMPHostIRFile.empty()) + return; + + auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile); + if (Buf.getError()) + return; + + llvm::LLVMContext C; + auto ME = llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C); + + if (ME.getError()) + return; + + llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info"); + if (!MD) + return; + + for (auto I : MD->operands()) { + llvm::MDNode *MN = cast(I); + + auto getMDInt = [&](unsigned Idx) { + llvm::ConstantAsMetadata *V = + cast(MN->getOperand(Idx)); + return cast(V->getValue())->getZExtValue(); + }; + + auto getMDString = [&](unsigned Idx) { + llvm::MDString *V = cast(MN->getOperand(Idx)); + return V->getString(); + }; + + switch (getMDInt(0)) { + default: + llvm_unreachable("Unexpected metadata!"); + break; + case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: + OFFLOAD_ENTRY_INFO_TARGET_REGION: + OffloadEntriesInfoManager.initializeTargetRegionEntryInfo( + /*DeviceID=*/getMDInt(1), /*FileID=*/getMDInt(2), + /*ParentName=*/getMDString(3), /*Line=*/getMDInt(4), + /*Column=*/getMDInt(5), /*Order=*/getMDInt(6)); + break; + } + } +} + void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) { if (!KmpRoutineEntryPtrTy) { // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type. @@ -1992,6 +2399,80 @@ static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC, return Field; } +QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() { + + // Make sure the type of the entry is already created. This is the type we + // have to create: + // struct __tgt_offload_entry{ + // void *addr; // Pointer to the offload entry info. + // // (function or global) + // char *name; // Name of the function or global. + // size_t size; // Size of the entry info (0 if it a function). + // }; + if (TgtOffloadEntryQTy.isNull()) { + ASTContext &C = CGM.getContext(); + auto *RD = C.buildImplicitRecord("__tgt_offload_entry"); + RD->startDefinition(); + addFieldToRecordDecl(C, RD, C.VoidPtrTy); + addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy)); + addFieldToRecordDecl(C, RD, C.getSizeType()); + RD->completeDefinition(); + TgtOffloadEntryQTy = C.getRecordType(RD); + } + return TgtOffloadEntryQTy; +} + +QualType CGOpenMPRuntime::getTgtDeviceImageQTy() { + // These are the types we need to build: + // struct __tgt_device_image{ + // void *ImageStart; // Pointer to the target code start. + // void *ImageEnd; // Pointer to the target code end. + // // We also add the host entries to the device image, as it may be useful + // // for the target runtime to have access to that information. + // __tgt_offload_entry *EntriesBegin; // Begin of the table with all + // // the entries. + // __tgt_offload_entry *EntriesEnd; // End of the table with all the + // // entries (non inclusive). + // }; + if (TgtDeviceImageQTy.isNull()) { + ASTContext &C = CGM.getContext(); + auto *RD = C.buildImplicitRecord("__tgt_device_image"); + RD->startDefinition(); + addFieldToRecordDecl(C, RD, C.VoidPtrTy); + addFieldToRecordDecl(C, RD, C.VoidPtrTy); + addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); + addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); + RD->completeDefinition(); + TgtDeviceImageQTy = C.getRecordType(RD); + } + return TgtDeviceImageQTy; +} + +QualType CGOpenMPRuntime::getTgtBinaryDescriptorQTy() { + // struct __tgt_bin_desc{ + // int32_t NumDevices; // Number of devices supported. + // __tgt_device_image *DeviceImages; // Arrays of device images + // // (one per device). + // __tgt_offload_entry *EntriesBegin; // Begin of the table with all the + // // entries. + // __tgt_offload_entry *EntriesEnd; // End of the table with all the + // // entries (non inclusive). + // }; + if (TgtBinaryDescriptorQTy.isNull()) { + ASTContext &C = CGM.getContext(); + auto *RD = C.buildImplicitRecord("__tgt_bin_desc"); + RD->startDefinition(); + addFieldToRecordDecl( + C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); + addFieldToRecordDecl(C, RD, C.getPointerType(getTgtDeviceImageQTy())); + addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); + addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); + RD->completeDefinition(); + TgtBinaryDescriptorQTy = C.getRecordType(RD); + } + return TgtBinaryDescriptorQTy; +} + namespace { struct PrivateHelpersTy { PrivateHelpersTy(const VarDecl *Original, const VarDecl *PrivateCopy, @@ -3238,20 +3719,115 @@ void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, } } -llvm::Value * -CGOpenMPRuntime::emitTargetOutlinedFunction(const OMPExecutableDirective &D, - const RegionCodeGenTy &CodeGen) { +/// \brief Obtain information that uniquely identifies a target entry. This +/// consists of the file and device IDs as well as line and column numbers +/// associated with the relevant entry source location. +static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc, + unsigned &DeviceID, unsigned &FileID, + unsigned &LineNum, unsigned &ColumnNum) { + + auto &SM = C.getSourceManager(); + + // The loc should be always valid and have a file ID (the user cannot use + // #pragma directives in macros) + + assert(Loc.isValid() && "Source location is expected to be always valid."); + assert(Loc.isFileID() && "Source location is expected to refer to a file."); + + PresumedLoc PLoc = SM.getPresumedLoc(Loc); + assert(PLoc.isValid() && "Source location is expected to be always valid."); + + llvm::sys::fs::UniqueID ID; + if (llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID)) + llvm_unreachable("Source file with target region no longer exists!"); + + DeviceID = ID.getDevice(); + FileID = ID.getFile(); + LineNum = PLoc.getLine(); + ColumnNum = PLoc.getColumn(); + return; +} + +void CGOpenMPRuntime::emitTargetOutlinedFunction( + const OMPExecutableDirective &D, StringRef ParentName, + llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, + bool IsOffloadEntry) { + + assert(!ParentName.empty() && "Invalid target region parent name!"); + const CapturedStmt &CS = *cast(D.getAssociatedStmt()); + // Emit target region as a standalone region. + auto &&CodeGen = [&CS](CodeGenFunction &CGF) { + CGF.EmitStmt(CS.getCapturedStmt()); + }; + + // Create a unique name for the proxy/entry function that using the source + // location information of the current target region. The name will be + // something like: + // + // .omp_offloading.DD_FFFF.PP.lBB.cCC + // + // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the + // mangled name of the function that encloses the target region, BB is the + // line number of the target region, and CC is the column number of the target + // region. + + unsigned DeviceID; + unsigned FileID; + unsigned Line; + unsigned Column; + getTargetEntryUniqueInfo(CGM.getContext(), D.getLocStart(), DeviceID, FileID, + Line, Column); + SmallString<64> EntryFnName; + { + llvm::raw_svector_ostream OS(EntryFnName); + OS << ".omp_offloading" << llvm::format(".%x", DeviceID) + << llvm::format(".%x.", FileID) << ParentName << ".l" << Line << ".c" + << Column; + } + CodeGenFunction CGF(CGM, true); - CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen); + CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName); CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); - return CGF.GenerateOpenMPCapturedStmtFunction(CS); + + OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS); + + // If this target outline function is not an offload entry, we don't need to + // register it. + if (!IsOffloadEntry) + return; + + // The target region ID is used by the runtime library to identify the current + // target region, so it only has to be unique and not necessarily point to + // anything. It could be the pointer to the outlined function that implements + // the target region, but we aren't using that so that the compiler doesn't + // need to keep that, and could therefore inline the host function if proven + // worthwhile during optimization. In the other hand, if emitting code for the + // device, the ID has to be the function address so that it can retrieved from + // the offloading entry and launched by the runtime library. We also mark the + // outlined function to have external linkage in case we are emitting code for + // the device, because these functions will be entry points to the device. + + if (CGM.getLangOpts().OpenMPIsDevice) { + OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy); + OutlinedFn->setLinkage(llvm::GlobalValue::ExternalLinkage); + } else + OutlinedFnID = new llvm::GlobalVariable( + CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, + llvm::GlobalValue::PrivateLinkage, + llvm::Constant::getNullValue(CGM.Int8Ty), ".omp_offload.region_id"); + + // Register the information for the entry associated with this target region. + OffloadEntriesInfoManager.registerTargetRegionEntryInfo( + DeviceID, FileID, ParentName, Line, Column, OutlinedFn, OutlinedFnID); + return; } void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, llvm::Value *OutlinedFn, + llvm::Value *OutlinedFnID, const Expr *IfCond, const Expr *Device, ArrayRef CapturedVars) { if (!CGF.HaveInsertPoint()) @@ -3275,6 +3851,8 @@ void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF, OMP_DEVICEID_UNDEF = -1, }; + assert(OutlinedFn && "Invalid outlined function!"); + auto &Ctx = CGF.getContext(); // Fill up the arrays with the all the captured variables. @@ -3373,7 +3951,7 @@ void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF, // Fill up the pointer arrays and transfer execution to the device. auto &&ThenGen = [this, &Ctx, &BasePointers, &Pointers, &Sizes, &MapTypes, - hasVLACaptures, Device, OffloadError, + hasVLACaptures, Device, OutlinedFnID, OffloadError, OffloadErrorQType](CodeGenFunction &CGF) { unsigned PointerNumVal = BasePointers.size(); llvm::Value *PointerNum = CGF.Builder.getInt32(PointerNumVal); @@ -3504,10 +4082,8 @@ void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF, // compiler doesn't need to keep that, and could therefore inline the host // function if proven worthwhile during optimization. - llvm::Value *HostPtr = new llvm::GlobalVariable( - CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, - llvm::GlobalValue::PrivateLinkage, - llvm::Constant::getNullValue(CGM.Int8Ty), ".offload_hstptr"); + // From this point on, we need to have an ID of the target region defined. + assert(OutlinedFnID && "Invalid outlined function ID!"); // Emit device ID if any. llvm::Value *DeviceID; @@ -3518,25 +4094,35 @@ void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF, DeviceID = CGF.Builder.getInt32(OMP_DEVICEID_UNDEF); llvm::Value *OffloadingArgs[] = { - DeviceID, HostPtr, PointerNum, BasePointersArray, - PointersArray, SizesArray, MapTypesArray}; + DeviceID, OutlinedFnID, PointerNum, BasePointersArray, + PointersArray, SizesArray, MapTypesArray}; auto Return = CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target), OffloadingArgs); CGF.EmitStoreOfScalar(Return, OffloadError); }; - if (IfCond) { - // Notify that the host version must be executed. - auto &&ElseGen = [this, OffloadError, - OffloadErrorQType](CodeGenFunction &CGF) { - CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/-1u), - OffloadError); - }; - emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen); + // Notify that the host version must be executed. + auto &&ElseGen = [this, OffloadError, + OffloadErrorQType](CodeGenFunction &CGF) { + CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/-1u), + OffloadError); + }; + + // If we have a target function ID it means that we need to support + // offloading, otherwise, just execute on the host. We need to execute on host + // regardless of the conditional in the if clause if, e.g., the user do not + // specify target triples. + if (OutlinedFnID) { + if (IfCond) { + emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen); + } else { + CodeGenFunction::RunCleanupsScope Scope(CGF); + ThenGen(CGF); + } } else { CodeGenFunction::RunCleanupsScope Scope(CGF); - ThenGen(CGF); + ElseGen(CGF); } // Check the error code and execute the host version if required. @@ -3553,3 +4139,120 @@ void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF, CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true); return; } + +void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S, + StringRef ParentName) { + if (!S) + return; + + // If we find a OMP target directive, codegen the outline function and + // register the result. + // FIXME: Add other directives with target when they become supported. + bool isTargetDirective = isa(S); + + if (isTargetDirective) { + auto *E = cast(S); + unsigned DeviceID; + unsigned FileID; + unsigned Line; + unsigned Column; + getTargetEntryUniqueInfo(CGM.getContext(), E->getLocStart(), DeviceID, + FileID, Line, Column); + + // Is this a target region that should not be emitted as an entry point? If + // so just signal we are done with this target region. + if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo( + DeviceID, FileID, ParentName, Line, Column)) + return; + + llvm::Function *Fn; + llvm::Constant *Addr; + emitTargetOutlinedFunction(*E, ParentName, Fn, Addr, + /*isOffloadEntry=*/true); + assert(Fn && Addr && "Target region emission failed."); + return; + } + + if (const OMPExecutableDirective *E = dyn_cast(S)) { + if (!E->getAssociatedStmt()) + return; + + scanForTargetRegionsFunctions( + cast(E->getAssociatedStmt())->getCapturedStmt(), + ParentName); + return; + } + + // If this is a lambda function, look into its body. + if (auto *L = dyn_cast(S)) + S = L->getBody(); + + // Keep looking for target regions recursively. + for (auto *II : S->children()) + scanForTargetRegionsFunctions(II, ParentName); + + return; +} + +bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) { + auto &FD = *cast(GD.getDecl()); + + // If emitting code for the host, we do not process FD here. Instead we do + // the normal code generation. + if (!CGM.getLangOpts().OpenMPIsDevice) + return false; + + // Try to detect target regions in the function. + scanForTargetRegionsFunctions(FD.getBody(), CGM.getMangledName(GD)); + + // We should not emit any function othen that the ones created during the + // scanning. Therefore, we signal that this function is completely dealt + // with. + return true; +} + +bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) { + if (!CGM.getLangOpts().OpenMPIsDevice) + return false; + + // Check if there are Ctors/Dtors in this declaration and look for target + // regions in it. We use the complete variant to produce the kernel name + // mangling. + QualType RDTy = cast(GD.getDecl())->getType(); + if (auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) { + for (auto *Ctor : RD->ctors()) { + StringRef ParentName = + CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete)); + scanForTargetRegionsFunctions(Ctor->getBody(), ParentName); + } + auto *Dtor = RD->getDestructor(); + if (Dtor) { + StringRef ParentName = + CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete)); + scanForTargetRegionsFunctions(Dtor->getBody(), ParentName); + } + } + + // If we are in target mode we do not emit any global (declare target is not + // implemented yet). Therefore we signal that GD was processed in this case. + return true; +} + +bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) { + auto *VD = GD.getDecl(); + if (isa(VD)) + return emitTargetFunctions(GD); + + return emitTargetGlobalVariable(GD); +} + +llvm::Function *CGOpenMPRuntime::emitRegistrationFunction() { + // If we have offloading in the current module, we need to emit the entries + // now and register the offloading descriptor. + createOffloadEntriesAndInfoMetadata(); + + // Create and register the offloading binary descriptors. This is the main + // entity that captures all the information about offloading in the current + // compilation unit. + return createOffloadingBinaryDescriptorRegistration(); +} diff --git a/lib/CodeGen/CGOpenMPRuntime.h b/lib/CodeGen/CGOpenMPRuntime.h index 992f9a8805e..a51c5baf8b5 100644 --- a/lib/CodeGen/CGOpenMPRuntime.h +++ b/lib/CodeGen/CGOpenMPRuntime.h @@ -35,6 +35,7 @@ class Value; namespace clang { class Expr; +class GlobalDecl; class OMPExecutableDirective; class VarDecl; @@ -165,6 +166,10 @@ class CGOpenMPRuntime { // arg_num, void** args_base, void **args, size_t *arg_sizes, int32_t // *arg_types); OMPRTL__tgt_target, + // Call to void __tgt_register_lib(__tgt_bin_desc *desc); + OMPRTL__tgt_register_lib, + // Call to void __tgt_unregister_lib(__tgt_bin_desc *desc); + OMPRTL__tgt_unregister_lib, }; /// \brief Values for bit flags used in the ident_t to describe the fields. @@ -288,7 +293,181 @@ class CGOpenMPRuntime { /// } flags; /// } kmp_depend_info_t; QualType KmpDependInfoTy; + /// \brief Type struct __tgt_offload_entry{ + /// void *addr; // Pointer to the offload entry info. + /// // (function or global) + /// char *name; // Name of the function or global. + /// size_t size; // Size of the entry info (0 if it a function). + /// }; + QualType TgtOffloadEntryQTy; + /// struct __tgt_device_image{ + /// void *ImageStart; // Pointer to the target code start. + /// void *ImageEnd; // Pointer to the target code end. + /// // We also add the host entries to the device image, as it may be useful + /// // for the target runtime to have access to that information. + /// __tgt_offload_entry *EntriesBegin; // Begin of the table with all + /// // the entries. + /// __tgt_offload_entry *EntriesEnd; // End of the table with all the + /// // entries (non inclusive). + /// }; + QualType TgtDeviceImageQTy; + /// struct __tgt_bin_desc{ + /// int32_t NumDevices; // Number of devices supported. + /// __tgt_device_image *DeviceImages; // Arrays of device images + /// // (one per device). + /// __tgt_offload_entry *EntriesBegin; // Begin of the table with all the + /// // entries. + /// __tgt_offload_entry *EntriesEnd; // End of the table with all the + /// // entries (non inclusive). + /// }; + QualType TgtBinaryDescriptorQTy; + /// \brief Entity that registers the offloading constants that were emitted so + /// far. + class OffloadEntriesInfoManagerTy { + CodeGenModule &CGM; + + /// \brief Number of entries registered so far. + unsigned OffloadingEntriesNum; + + public: + /// \brief Base class of the entries info. + class OffloadEntryInfo { + public: + /// \brief Kind of a given entry. Currently, only target regions are + /// supported. + enum OffloadingEntryInfoKinds { + // Entry is a target region. + OFFLOAD_ENTRY_INFO_TARGET_REGION = 0, + // Invalid entry info. + OFFLOAD_ENTRY_INFO_INVALID = ~0u + }; + + OffloadEntryInfo() : Order(~0u), Kind(OFFLOAD_ENTRY_INFO_INVALID) {} + explicit OffloadEntryInfo(OffloadingEntryInfoKinds Kind, unsigned Order) + : Order(Order), Kind(Kind) {} + + bool isValid() const { return Order != ~0u; } + unsigned getOrder() const { return Order; } + OffloadingEntryInfoKinds getKind() const { return Kind; } + static bool classof(const OffloadEntryInfo *Info) { return true; } + + protected: + // \brief Order this entry was emitted. + unsigned Order; + + OffloadingEntryInfoKinds Kind; + }; + + /// \brief Return true if a there are no entries defined. + bool empty() const; + /// \brief Return number of entries defined so far. + unsigned size() const { return OffloadingEntriesNum; } + OffloadEntriesInfoManagerTy(CodeGenModule &CGM) + : CGM(CGM), OffloadingEntriesNum(0) {} + + /// + /// Target region entries related. + /// + /// \brief Target region entries info. + class OffloadEntryInfoTargetRegion : public OffloadEntryInfo { + // \brief Address of the entity that has to be mapped for offloading. + llvm::Constant *Addr; + // \brief Address that can be used as the ID of the entry. + llvm::Constant *ID; + + public: + OffloadEntryInfoTargetRegion() + : OffloadEntryInfo(OFFLOAD_ENTRY_INFO_TARGET_REGION, ~0u), + Addr(nullptr), ID(nullptr) {} + explicit OffloadEntryInfoTargetRegion(unsigned Order, + llvm::Constant *Addr, + llvm::Constant *ID) + : OffloadEntryInfo(OFFLOAD_ENTRY_INFO_TARGET_REGION, Order), + Addr(Addr), ID(ID) {} + + llvm::Constant *getAddress() const { return Addr; } + llvm::Constant *getID() const { return ID; } + void setAddress(llvm::Constant *V) { + assert(!Addr && "Address as been set before!"); + Addr = V; + } + void setID(llvm::Constant *V) { + assert(!ID && "ID as been set before!"); + ID = V; + } + static bool classof(const OffloadEntryInfo *Info) { + return Info->getKind() == OFFLOAD_ENTRY_INFO_TARGET_REGION; + } + }; + /// \brief Initialize target region entry. + void initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, + StringRef ParentName, unsigned LineNum, + unsigned ColNum, unsigned Order); + /// \brief Register target region entry. + void registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, + StringRef ParentName, unsigned LineNum, + unsigned ColNum, llvm::Constant *Addr, + llvm::Constant *ID); + /// \brief Return true if a target region entry with the provided + /// information exists. + bool hasTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, + StringRef ParentName, unsigned LineNum, + unsigned ColNum) const; + /// brief Applies action \a Action on all registered entries. + typedef llvm::function_ref + OffloadTargetRegionEntryInfoActTy; + void actOnTargetRegionEntriesInfo( + const OffloadTargetRegionEntryInfoActTy &Action); + + private: + // Storage for target region entries kind. The storage is to be indexed by + // file ID, device ID, parent function name, lane number, and column number. + typedef llvm::DenseMap + OffloadEntriesTargetRegionPerColumn; + typedef llvm::DenseMap + OffloadEntriesTargetRegionPerLine; + typedef llvm::StringMap + OffloadEntriesTargetRegionPerParentName; + typedef llvm::DenseMap + OffloadEntriesTargetRegionPerFile; + typedef llvm::DenseMap + OffloadEntriesTargetRegionPerDevice; + typedef OffloadEntriesTargetRegionPerDevice OffloadEntriesTargetRegionTy; + OffloadEntriesTargetRegionTy OffloadEntriesTargetRegion; + }; + OffloadEntriesInfoManagerTy OffloadEntriesInfoManager; + + /// \brief Creates and registers offloading binary descriptor for the current + /// compilation unit. The function that does the registration is returned. + llvm::Function *createOffloadingBinaryDescriptorRegistration(); + + /// \brief Creates offloading entry for the provided address \a Addr, + /// name \a Name and size \a Size. + void createOffloadEntry(llvm::Constant *Addr, StringRef Name, uint64_t Size); + + /// \brief Creates all the offload entries in the current compilation unit + /// along with the associated metadata. + void createOffloadEntriesAndInfoMetadata(); + + /// \brief Loads all the offload entries information from the host IR + /// metadata. + void loadOffloadInfoMetadata(); + /// \brief Returns __tgt_offload_entry type. + QualType getTgtOffloadEntryQTy(); + + /// \brief Returns __tgt_device_image type. + QualType getTgtDeviceImageQTy(); + + /// \brief Returns __tgt_bin_desc type. + QualType getTgtBinaryDescriptorQTy(); + + /// \brief Start scanning from statement \a S and and emit all target regions + /// found along the way. + /// \param S Starting statement. + /// \param ParentName Name of the function declaration that is being scanned. + void scanForTargetRegionsFunctions(const Stmt *S, StringRef ParentName); /// \brief Build type kmp_routine_entry_t (if not built yet). void emitKmpRoutineEntryT(QualType KmpInt32Ty); @@ -743,16 +922,24 @@ class CGOpenMPRuntime { /// \brief Emit outilined function for 'target' directive. /// \param D Directive to emit. - /// \param CodeGen Code generation sequence for the \a D directive. - virtual llvm::Value * - emitTargetOutlinedFunction(const OMPExecutableDirective &D, - const RegionCodeGenTy &CodeGen); + /// \param ParentName Name of the function that encloses the target region. + /// \param OutlinedFn Outlined function value to be defined by this call. + /// \param OutlinedFnID Outlined function ID value to be defined by this call. + /// \param IsOffloadEntry True if the outlined function is an offload entry. + /// An oulined function may not be an entry if, e.g. the if clause always + /// evaluates to false. + virtual void emitTargetOutlinedFunction(const OMPExecutableDirective &D, + StringRef ParentName, + llvm::Function *&OutlinedFn, + llvm::Constant *&OutlinedFnID, + bool IsOffloadEntry); /// \brief Emit the target offloading code associated with \a D. The emitted /// code attempts offloading the execution to the device, an the event of /// a failure it executes the host version outlined in \a OutlinedFn. /// \param D Directive to emit. /// \param OutlinedFn Host version of the code to be offloaded. + /// \param OutlinedFnID ID of host version of the code to be offloaded. /// \param IfCond Expression evaluated in if clause associated with the target /// directive, or null if no if clause is used. /// \param Device Expression evaluated in device clause associated with the @@ -760,9 +947,31 @@ class CGOpenMPRuntime { /// \param CapturedVars Values captured in the current region. virtual void emitTargetCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, - llvm::Value *OutlinedFn, const Expr *IfCond, + llvm::Value *OutlinedFn, + llvm::Value *OutlinedFnID, const Expr *IfCond, const Expr *Device, ArrayRef CapturedVars); + + /// \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 GD Function to scan. + virtual bool emitTargetFunctions(GlobalDecl GD); + + /// \brief Emit the global variable if it is a valid device global variable. + /// Returns true if \a GD was dealt with successfully. + /// \param GD Variable declaration to emit. + virtual bool emitTargetGlobalVariable(GlobalDecl GD); + + /// \brief Emit the global \a GD if it is meaningful for the target. Returns + /// if it was emitted succesfully. + /// \param GD Global to scan. + virtual bool emitTargetGlobal(GlobalDecl GD); + + /// \brief Creates the offloading descriptor in the event any target region + /// was emitted in the current module and return the function that registers + /// it. + virtual llvm::Function *emitRegistrationFunction(); }; } // namespace CodeGen diff --git a/lib/CodeGen/CGStmtOpenMP.cpp b/lib/CodeGen/CGStmtOpenMP.cpp index 82011984f8e..14917c20c53 100644 --- a/lib/CodeGen/CGStmtOpenMP.cpp +++ b/lib/CodeGen/CGStmtOpenMP.cpp @@ -2571,14 +2571,8 @@ void CodeGenFunction::EmitOMPTargetDirective(const OMPTargetDirective &S) { llvm::SmallVector CapturedVars; GenerateOpenMPCapturedVars(CS, CapturedVars); - // Emit target region as a standalone region. - auto &&CodeGen = [&CS](CodeGenFunction &CGF) { - CGF.EmitStmt(CS.getCapturedStmt()); - }; - - // Obtain the target region outlined function. - llvm::Value *Fn = - CGM.getOpenMPRuntime().emitTargetOutlinedFunction(S, CodeGen); + llvm::Function *Fn = nullptr; + llvm::Constant *FnID = nullptr; // Check if we have any if clause associated with the directive. const Expr *IfCond = nullptr; @@ -2593,7 +2587,34 @@ void CodeGenFunction::EmitOMPTargetDirective(const OMPTargetDirective &S) { Device = C->getDevice(); } - CGM.getOpenMPRuntime().emitTargetCall(*this, S, Fn, IfCond, Device, + // Check if we have an if clause whose conditional always evaluates to false + // or if we do not have any targets specified. If so the target region is not + // an offload entry point. + bool IsOffloadEntry = true; + if (IfCond) { + bool Val; + if (ConstantFoldsToSimpleInteger(IfCond, Val) && !Val) + IsOffloadEntry = false; + } + if (CGM.getLangOpts().OMPTargetTriples.empty()) + IsOffloadEntry = false; + + assert(CurFuncDecl && "No parent declaration for target region!"); + StringRef ParentName; + // In case we have Ctors/Dtors we use the complete type variant to produce + // the mangling of the device outlined kernel. + if (auto *D = dyn_cast(CurFuncDecl)) + ParentName = CGM.getMangledName(GlobalDecl(D, Ctor_Complete)); + else if (auto *D = dyn_cast(CurFuncDecl)) + ParentName = CGM.getMangledName(GlobalDecl(D, Dtor_Complete)); + else + ParentName = + CGM.getMangledName(GlobalDecl(cast(CurFuncDecl))); + + CGM.getOpenMPRuntime().emitTargetOutlinedFunction(S, ParentName, Fn, FnID, + IsOffloadEntry); + + CGM.getOpenMPRuntime().emitTargetCall(*this, S, Fn, FnID, IfCond, Device, CapturedVars); } diff --git a/lib/CodeGen/CGVTables.cpp b/lib/CodeGen/CGVTables.cpp index c8f3add6776..a40aab29be0 100644 --- a/lib/CodeGen/CGVTables.cpp +++ b/lib/CodeGen/CGVTables.cpp @@ -378,8 +378,8 @@ void CodeGenFunction::EmitMustTailThunk(const CXXMethodDecl *MD, // Apply the standard set of call attributes. unsigned CallingConv; CodeGen::AttributeListType AttributeList; - CGM.ConstructAttributeList(*CurFnInfo, MD, AttributeList, CallingConv, - /*AttrOnCallSite=*/true); + CGM.ConstructAttributeList(Callee->getName(), *CurFnInfo, MD, AttributeList, + CallingConv, /*AttrOnCallSite=*/true); llvm::AttributeSet Attrs = llvm::AttributeSet::get(getLLVMContext(), AttributeList); Call->setAttributes(Attrs); diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index cad179fda53..4c01ac5ed09 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -376,6 +376,10 @@ void CodeGenModule::Release() { if (llvm::Function *CudaDtorFunction = CUDARuntime->makeModuleDtorFunction()) AddGlobalDtor(CudaDtorFunction); } + if (OpenMPRuntime) + if (llvm::Function *OpenMPRegistrationFunction = + OpenMPRuntime->emitRegistrationFunction()) + AddGlobalCtor(OpenMPRegistrationFunction, 0); if (PGOReader) { getModule().setMaximumFunctionCount(PGOReader->getMaximumFunctionCount()); if (PGOStats.hasDiagnostics()) @@ -771,7 +775,8 @@ void CodeGenModule::SetLLVMFunctionAttributes(const Decl *D, llvm::Function *F) { unsigned CallingConv; AttributeListType AttributeList; - ConstructAttributeList(Info, D, AttributeList, CallingConv, false); + ConstructAttributeList(F->getName(), Info, D, AttributeList, CallingConv, + false); F->setAttributes(llvm::AttributeSet::get(getLLVMContext(), AttributeList)); F->setCallingConv(static_cast(CallingConv)); } @@ -1491,6 +1496,11 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) { } } + // If this is OpenMP device, check if it is legal to emit this global + // normally. + if (OpenMPRuntime && OpenMPRuntime->emitTargetGlobal(GD)) + return; + // Ignore declarations, they will be emitted on their first use. if (const auto *FD = dyn_cast(Global)) { // Forward declarations are emitted lazily on first use. @@ -3597,6 +3607,9 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { // File-scope asm is ignored during device-side CUDA compilation. if (LangOpts.CUDA && LangOpts.CUDAIsDevice) break; + // File-scope asm is ignored during device-side OpenMP compilation. + if (LangOpts.OpenMPIsDevice) + break; auto *AD = cast(D); getModule().appendModuleInlineAsm(AD->getAsmString()->getString()); break; diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index 33113837a4c..fdb4d78b355 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -966,13 +966,14 @@ class CodeGenModule : public CodeGenTypeCache { /// Get the LLVM attributes and calling convention to use for a particular /// function type. /// + /// \param Name - The function name. /// \param Info - The function type information. /// \param CalleeInfo - The callee information these attributes are being /// constructed for. If valid, the attributes applied to this decl may /// contribute to the function attributes and calling convention. /// \param PAL [out] - On return, the attribute list to use. /// \param CallingConv [out] - On return, the LLVM calling convention to use. - void ConstructAttributeList(const CGFunctionInfo &Info, + void ConstructAttributeList(StringRef Name, const CGFunctionInfo &Info, CGCalleeInfo CalleeInfo, AttributeListType &PAL, unsigned &CallingConv, bool AttrOnCallSite); diff --git a/lib/CodeGen/CodeGenPGO.cpp b/lib/CodeGen/CodeGenPGO.cpp index 38774332f31..2c0d93b394a 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) { @@ -721,17 +721,7 @@ CodeGenPGO::applyFunctionAttributes(llvm::IndexedInstrProfReader *PGOReader, if (!haveRegionCounts()) return; - uint64_t MaxFunctionCount = PGOReader->getMaximumFunctionCount(); uint64_t FunctionCount = getRegionCount(nullptr); - if (FunctionCount >= (uint64_t)(0.3 * (double)MaxFunctionCount)) - // Turn on InlineHint attribute for hot functions. - // FIXME: 30% is from preliminary tuning on SPEC, it may not be optimal. - Fn->addFnAttr(llvm::Attribute::InlineHint); - else if (FunctionCount <= (uint64_t)(0.01 * (double)MaxFunctionCount)) - // Turn on Cold attribute for cold functions. - // FIXME: 1% is from preliminary tuning on SPEC, it may not be optimal. - Fn->addFnAttr(llvm::Attribute::Cold); - Fn->setEntryCount(FunctionCount); } diff --git a/lib/CodeGen/CoverageMappingGen.cpp b/lib/CodeGen/CoverageMappingGen.cpp index 1d4d7099e19..03e22cd398a 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 0d1bf6d975c..9ae2bcffe4c 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 @@ class CoverageMappingModuleGen { 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/ObjectFilePCHContainerOperations.cpp b/lib/CodeGen/ObjectFilePCHContainerOperations.cpp index b397eb352a6..f385e53fa01 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 @@ class PCHContainerGenerator : public ASTConsumer { // 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 @@ class PCHContainerGenerator : public ASTConsumer { 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/Driver.cpp b/lib/Driver/Driver.cpp index 11c4e6e58c4..2834fcbc8db 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -699,11 +699,11 @@ void Driver::generateCompilationDiagnostics(Compilation &C, } void Driver::setUpResponseFiles(Compilation &C, Command &Cmd) { - // Since argumentsFitWithinSystemLimits() may underestimate system's capacity + // Since commandLineFitsWithinSystemLimits() may underestimate system's capacity // if the tool does not support response files, there is a chance/ that things // will just work without a response file, so we silently just skip it. if (Cmd.getCreator().getResponseFilesSupport() == Tool::RF_None || - llvm::sys::argumentsFitWithinSystemLimits(Cmd.getArguments())) + llvm::sys::commandLineFitsWithinSystemLimits(Cmd.getExecutable(), Cmd.getArguments())) return; std::string TmpName = GetTemporaryPath("response", "txt"); diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index b02430e0176..b9768a42fdf 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -2611,7 +2611,8 @@ void HexagonToolChain::getHexagonLibraryPaths(const ArgList &Args, // Other standard paths //---------------------------------------------------------------------------- std::vector RootDirs; - std::copy(D.PrefixDirs.begin(), D.PrefixDirs.end(), RootDirs.begin()); + std::copy(D.PrefixDirs.begin(), D.PrefixDirs.end(), + std::back_inserter(RootDirs)); std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(), D.PrefixDirs); @@ -2715,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/Tools.cpp b/lib/Driver/Tools.cpp index bf0470bbd1e..ec7db3d6f8a 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -938,8 +938,8 @@ static void getARMTargetFeatures(const ToolChain &TC, if (Args.hasArg(options::OPT_ffixed_r9)) Features.push_back("+reserve-r9"); - // The kext and FreeBSD linkers don't know how to deal with movw/movt. - if (KernelOrKext || Triple.isOSFreeBSD()) + // The kext linker doesn't know how to deal with movw/movt. + if (KernelOrKext || Args.hasArg(options::OPT_mno_movt)) Features.push_back("+no-movt"); } @@ -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) { @@ -2107,7 +2117,7 @@ static bool DecodeAArch64Mcpu(const Driver &D, StringRef Mcpu, StringRef &CPU, std::pair Split = Mcpu.split("+"); CPU = Split.first; if (CPU == "cyclone" || CPU == "cortex-a53" || CPU == "cortex-a57" || - CPU == "cortex-a72" || CPU == "cortex-a35") { + CPU == "cortex-a72" || CPU == "cortex-a35" || CPU == "exynos-m1") { Features.push_back("+neon"); Features.push_back("+crc"); Features.push_back("+crypto"); @@ -3592,6 +3602,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (!IsWindowsMSVC) CmdArgs.push_back("-analyzer-checker=unix"); + // Disable some unix checkers for PS4. + if (IsPS4CPU) { + CmdArgs.push_back("-analyzer-disable-checker=unix.API"); + CmdArgs.push_back("-analyzer-disable-checker=unix.Vfork"); + } + if (getToolChain().getTriple().getVendor() == llvm::Triple::Apple) CmdArgs.push_back("-analyzer-checker=osx"); @@ -3600,14 +3616,15 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (types::isCXX(Input.getType())) CmdArgs.push_back("-analyzer-checker=cplusplus"); - // Enable the following experimental checkers for testing. - CmdArgs.push_back( - "-analyzer-checker=security.insecureAPI.UncheckedReturn"); - CmdArgs.push_back("-analyzer-checker=security.insecureAPI.getpw"); - CmdArgs.push_back("-analyzer-checker=security.insecureAPI.gets"); - CmdArgs.push_back("-analyzer-checker=security.insecureAPI.mktemp"); - CmdArgs.push_back("-analyzer-checker=security.insecureAPI.mkstemp"); - CmdArgs.push_back("-analyzer-checker=security.insecureAPI.vfork"); + if (!IsPS4CPU) { + CmdArgs.push_back( + "-analyzer-checker=security.insecureAPI.UncheckedReturn"); + CmdArgs.push_back("-analyzer-checker=security.insecureAPI.getpw"); + CmdArgs.push_back("-analyzer-checker=security.insecureAPI.gets"); + CmdArgs.push_back("-analyzer-checker=security.insecureAPI.mktemp"); + CmdArgs.push_back("-analyzer-checker=security.insecureAPI.mkstemp"); + CmdArgs.push_back("-analyzer-checker=security.insecureAPI.vfork"); + } // Default nullability checks. CmdArgs.push_back("-analyzer-checker=nullability.NullPassedToNonnull"); @@ -4008,6 +4025,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 @@ -4169,8 +4191,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)) { @@ -4733,11 +4758,33 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, A->render(Args, CmdArgs); } - // -fbuiltin is default unless -mkernel is used - if (!Args.hasFlag(options::OPT_fbuiltin, options::OPT_fno_builtin, - !Args.hasArg(options::OPT_mkernel))) + // -fbuiltin is default unless -mkernel is used. + bool UseBuiltins = + Args.hasFlag(options::OPT_fbuiltin, options::OPT_fno_builtin, + !Args.hasArg(options::OPT_mkernel)); + if (!UseBuiltins) CmdArgs.push_back("-fno-builtin"); + // -ffreestanding implies -fno-builtin. + if (Args.hasArg(options::OPT_ffreestanding)) + UseBuiltins = false; + + // Process the -fno-builtin-* options. + for (const auto &Arg : Args) { + const Option &O = Arg->getOption(); + if (!O.matches(options::OPT_fno_builtin_)) + continue; + + Arg->claim(); + // If -fno-builtin is specified, then there's no need to pass the option to + // the frontend. + if (!UseBuiltins) + continue; + + StringRef FuncName = Arg->getValue(); + CmdArgs.push_back(Args.MakeArgString("-fno-builtin-" + FuncName)); + } + if (!Args.hasFlag(options::OPT_fassume_sane_operator_new, options::OPT_fno_assume_sane_operator_new)) CmdArgs.push_back("-fno-assume-sane-operator-new"); @@ -6011,8 +6058,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()); @@ -6049,6 +6095,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)) @@ -6059,11 +6111,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); } } @@ -6179,6 +6226,11 @@ void gcc::Compiler::RenderExtraToolArgs(const JobAction &JA, case types::TY_LTO_BC: CmdArgs.push_back("-c"); break; + // We assume we've got an "integrated" assembler in that gcc will produce an + // object file itself. + case types::TY_Object: + CmdArgs.push_back("-c"); + break; case types::TY_PP_Asm: CmdArgs.push_back("-S"); break; @@ -6500,6 +6552,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()); @@ -9473,6 +9533,8 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA, A.renderAsInput(Args, CmdArgs); } + TC.addProfileRTLibs(Args, CmdArgs); + // We need to special case some linker paths. In the case of lld, we need to // translate 'lld' into 'lld-link', and in the case of the regular msvc // linker, we need to use a special search algorithm. diff --git a/lib/Driver/Tools.h b/lib/Driver/Tools.h index 314315dea00..6c67819a34a 100644 --- a/lib/Driver/Tools.h +++ b/lib/Driver/Tools.h @@ -82,6 +82,8 @@ class LLVM_LIBRARY_VISIBILITY Clang : public Tool { 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 }; @@ -149,6 +151,10 @@ class LLVM_LIBRARY_VISIBILITY Common : public GnuTool { Common(const char *Name, const char *ShortName, const ToolChain &TC) : GnuTool(Name, ShortName, TC) {} + // A gcc tool has an "integrated" assembler that it will call to produce an + // object. Let it use that assembler so that we don't have to deal with + // assembly syntax incompatibilities. + bool hasIntegratedAssembler() const override { return true; } void ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const llvm::opt::ArgList &TCArgs, diff --git a/lib/Format/ContinuationIndenter.cpp b/lib/Format/ContinuationIndenter.cpp index ad8f7980118..62bd4b3ce5a 100644 --- a/lib/Format/ContinuationIndenter.cpp +++ b/lib/Format/ContinuationIndenter.cpp @@ -38,6 +38,12 @@ static unsigned getLengthToMatchingParen(const FormatToken &Tok) { return End->TotalLength - Tok.TotalLength + 1; } +static unsigned getLengthToNextOperator(const FormatToken &Tok) { + if (!Tok.NextOperator) + return 0; + return Tok.NextOperator->TotalLength - Tok.TotalLength; +} + // Returns \c true if \c Tok is the "." or "->" of a call and starts the next // segment of a builder type call. static bool startsSegmentOfBuilderTypeCall(const FormatToken &Tok) { @@ -171,9 +177,13 @@ bool ContinuationIndenter::mustBreak(const LineState &State) { return true; unsigned NewLineColumn = getNewLineColumn(State); - if (State.Column < NewLineColumn) + if (State.Column <= NewLineColumn) return false; + if (Current.isMemberAccess() && + State.Column + getLengthToNextOperator(Current) > Style.ColumnLimit) + return true; + if (Style.AlwaysBreakBeforeMultilineStrings && (NewLineColumn == State.FirstIndent + Style.ContinuationIndentWidth || Previous.is(tok::comma) || Current.NestingLevel < 2) && @@ -247,8 +257,10 @@ bool ContinuationIndenter::mustBreak(const LineState &State) { Previous.is(tok::l_brace) && !Current.isOneOf(tok::r_brace, tok::comment)) return true; - if (Current.is(tok::lessless) && Previous.is(tok::identifier) && - Previous.TokenText == "endl") + if (Current.is(tok::lessless) && + ((Previous.is(tok::identifier) && Previous.TokenText == "endl") || + (Previous.Tok.isLiteral() && (Previous.TokenText.endswith("\\n\"") || + Previous.TokenText == "\'\\n\'")))) return true; return false; @@ -378,7 +390,7 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun, TT_CtorInitializerColon)) && ((Previous.getPrecedence() != prec::Assignment && (Previous.isNot(tok::lessless) || Previous.OperatorIndex != 0 || - !Previous.LastOperator)) || + Previous.NextOperator)) || Current.StartsBinaryExpression)) { // Always indent relative to the RHS of the expression unless this is a // simple assignment without binary expression on the RHS. Also indent @@ -693,7 +705,7 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State, std::min(State.LowestLevelOnLine, Current.NestingLevel); if (Current.isMemberAccess()) State.Stack.back().StartOfFunctionCall = - Current.LastOperator ? 0 : State.Column; + !Current.NextOperator ? 0 : State.Column; if (Current.is(TT_SelectorName)) { State.Stack.back().ObjCSelectorNameFound = true; if (Style.IndentWrappedFunctionNames) { @@ -848,7 +860,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; diff --git a/lib/Format/FormatToken.h b/lib/Format/FormatToken.h index 78bc0edc45c..b683660f350 100644 --- a/lib/Format/FormatToken.h +++ b/lib/Format/FormatToken.h @@ -248,9 +248,9 @@ struct FormatToken { /// with the same precedence, contains the 0-based operator index. unsigned OperatorIndex = 0; - /// \brief Is this the last operator (or "."/"->") in a sequence of operators - /// with the same precedence? - bool LastOperator = false; + /// \brief If this is an operator (or "."/"->") in a sequence of operators + /// with the same precedence, points to the next operator. + FormatToken *NextOperator = nullptr; /// \brief Is this token part of a \c DeclStmt defining multiple variables? /// diff --git a/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp index f5a33d4ddf2..7390865d4cc 100644 --- a/lib/Format/TokenAnnotator.cpp +++ b/lib/Format/TokenAnnotator.cpp @@ -199,6 +199,18 @@ class AnnotatingParser { 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) { @@ -1330,6 +1342,8 @@ class ExpressionParser { } else { // Operator found. if (CurrentPrecedence == Precedence) { + if (LatestOperator) + LatestOperator->NextOperator = Current; LatestOperator = Current; Current->OperatorIndex = OperatorIndex; ++OperatorIndex; @@ -1339,7 +1353,7 @@ class ExpressionParser { } if (LatestOperator && (Current || Precedence > 0)) { - LatestOperator->LastOperator = true; + // LatestOperator->LastOperator = true; if (Precedence == PrecedenceArrowAndPeriod) { // Call expressions don't have a binary operator precedence. addFakeParenthesis(Start, prec::Unknown); @@ -1771,7 +1785,15 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line, // which might otherwise be blown up onto many lines. Here, clang-format // won't produce "hanging" indents anyway as there is no other trailing // call. - return Right.LastOperator ? 150 : 35; + // + // Also apply higher penalty is not a call as that might lead to a wrapping + // like: + // + // aaaaaaa + // .aaaaaaaaa.bbbbbbbb(cccccccc); + return !Right.NextOperator || !Right.NextOperator->Previous->closesScope() + ? 150 + : 35; } if (Right.is(TT_TrailingAnnotation) && @@ -1823,7 +1845,7 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line, if (Right.is(tok::lessless)) { if (Left.is(tok::string_literal) && - (!Right.LastOperator || Right.OperatorIndex != 1)) { + (Right.NextOperator || Right.OperatorIndex != 1)) { StringRef Content = Left.TokenText; if (Content.startswith("\"")) Content = Content.drop_front(1); diff --git a/lib/Format/UnwrappedLineParser.cpp b/lib/Format/UnwrappedLineParser.cpp index 94b84988194..27e2f84d245 100644 --- a/lib/Format/UnwrappedLineParser.cpp +++ b/lib/Format/UnwrappedLineParser.cpp @@ -1796,14 +1796,13 @@ void UnwrappedLineParser::parseJavaScriptEs6ImportExport() { 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(); + } } } diff --git a/lib/Frontend/CodeGenOptions.cpp b/lib/Frontend/CodeGenOptions.cpp index 75ee47f8680..50bb9f951be 100644 --- a/lib/Frontend/CodeGenOptions.cpp +++ b/lib/Frontend/CodeGenOptions.cpp @@ -21,4 +21,12 @@ CodeGenOptions::CodeGenOptions() { memcpy(CoverageVersion, "402*", 4); } +bool CodeGenOptions::isNoBuiltinFunc(const char *Name) const { + StringRef FuncName(Name); + for (unsigned i = 0, e = NoBuiltinFuncs.size(); i != e; ++i) + if (FuncName.equals(NoBuiltinFuncs[i])) + return true; + return false; +} + } // end namespace clang diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index d3870424b6b..3a32f476566 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -8,13 +8,14 @@ //===----------------------------------------------------------------------===// #include "TestModuleFileExtension.h" -#include "clang/Frontend/CompilerInvocation.h" +#include "clang/Basic/Builtins.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/Version.h" #include "clang/Config/config.h" #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Options.h" #include "clang/Driver/Util.h" +#include "clang/Frontend/CompilerInvocation.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Frontend/LangStandard.h" #include "clang/Frontend/Utils.h" @@ -135,6 +136,20 @@ static void addDiagnosticArgs(ArgList &Args, OptSpecifier Group, } } +static void getAllNoBuiltinFuncValues(ArgList &Args, + std::vector &Funcs) { + SmallVector Values; + for (const auto &Arg : Args) { + const Option &O = Arg->getOption(); + if (O.matches(options::OPT_fno_builtin_)) { + const char *FuncName = Arg->getValue(); + if (Builtin::Context::isBuiltinFunc(FuncName)) + Values.push_back(FuncName); + } + } + Funcs.insert(Funcs.end(), Values.begin(), Values.end()); +} + static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args, DiagnosticsEngine &Diags) { using namespace options; @@ -399,18 +414,29 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, } if (Arg *A = Args.getLastArg(OPT_debug_info_kind_EQ)) { - Opts.setDebugInfo( - llvm::StringSwitch(A->getValue()) + unsigned Val = + llvm::StringSwitch(A->getValue()) .Case("line-tables-only", CodeGenOptions::DebugLineTablesOnly) .Case("limited", CodeGenOptions::LimitedDebugInfo) - .Case("standalone", CodeGenOptions::FullDebugInfo)); + .Case("standalone", CodeGenOptions::FullDebugInfo) + .Default(~0U); + if (Val == ~0U) + Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) + << A->getValue(); + else + Opts.setDebugInfo(static_cast(Val)); } if (Arg *A = Args.getLastArg(OPT_debugger_tuning_EQ)) { - Opts.setDebuggerTuning( - llvm::StringSwitch(A->getValue()) - .Case("gdb", CodeGenOptions::DebuggerKindGDB) - .Case("lldb", CodeGenOptions::DebuggerKindLLDB) - .Case("sce", CodeGenOptions::DebuggerKindSCE)); + unsigned Val = llvm::StringSwitch(A->getValue()) + .Case("gdb", CodeGenOptions::DebuggerKindGDB) + .Case("lldb", CodeGenOptions::DebuggerKindLLDB) + .Case("sce", CodeGenOptions::DebuggerKindSCE) + .Default(~0U); + if (Val == ~0U) + Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) + << A->getValue(); + else + Opts.setDebuggerTuning(static_cast(Val)); } Opts.DwarfVersion = getLastArgIntValue(Args, OPT_dwarf_version_EQ, 0, Diags); Opts.DebugColumnInfo = Args.hasArg(OPT_dwarf_column_info); @@ -441,6 +467,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.OptimizeSize = getOptimizationLevelSize(Args); Opts.SimplifyLibCalls = !(Args.hasArg(OPT_fno_builtin) || Args.hasArg(OPT_ffreestanding)); + if (Opts.SimplifyLibCalls) + getAllNoBuiltinFuncValues(Args, Opts.NoBuiltinFuncs); Opts.UnrollLoops = Args.hasFlag(OPT_funroll_loops, OPT_fno_unroll_loops, (Opts.OptimizationLevel > 1 && !Opts.OptimizeSize)); @@ -1658,6 +1686,8 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.ShortEnums = Args.hasArg(OPT_fshort_enums); Opts.Freestanding = Args.hasArg(OPT_ffreestanding); Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding; + if (!Opts.NoBuiltin) + getAllNoBuiltinFuncValues(Args, Opts.NoBuiltinFuncs); Opts.NoMathBuiltin = Args.hasArg(OPT_fno_math_builtin); Opts.AssumeSaneOperatorNew = !Args.hasArg(OPT_fno_assume_sane_operator_new); Opts.SizedDeallocation = Args.hasArg(OPT_fsized_deallocation); @@ -1784,6 +1814,30 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.OpenMP = Args.hasArg(options::OPT_fopenmp); Opts.OpenMPUseTLS = Opts.OpenMP && !Args.hasArg(options::OPT_fnoopenmp_use_tls); + Opts.OpenMPIsDevice = + Opts.OpenMP && Args.hasArg(options::OPT_fopenmp_is_device); + + // Get the OpenMP target triples if any. + if (Arg *A = Args.getLastArg(options::OPT_omptargets_EQ)) { + + for (unsigned i = 0; i < A->getNumValues(); ++i) { + llvm::Triple TT(A->getValue(i)); + + if (TT.getArch() == llvm::Triple::UnknownArch) + Diags.Report(clang::diag::err_drv_invalid_omp_target) << A->getValue(i); + else + Opts.OMPTargetTriples.push_back(TT); + } + } + + // Get OpenMP host file path if any and report if a non existent file is + // found + if (Arg *A = Args.getLastArg(options::OPT_omp_host_ir_file_path)) { + Opts.OMPHostIRFile = A->getValue(); + if (!llvm::sys::fs::exists(Opts.OMPHostIRFile)) + Diags.Report(clang::diag::err_drv_omp_host_ir_file_not_found) + << Opts.OMPHostIRFile; + } // Record whether the __DEPRECATED define was requested. Opts.Deprecated = Args.hasFlag(OPT_fdeprecated_macro, diff --git a/lib/Frontend/MultiplexConsumer.cpp b/lib/Frontend/MultiplexConsumer.cpp index 12c85240bd7..f8b73e9034b 100644 --- a/lib/Frontend/MultiplexConsumer.cpp +++ b/lib/Frontend/MultiplexConsumer.cpp @@ -119,6 +119,7 @@ class MultiplexASTMutationListener : public ASTMutationListener { 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/Lex/LiteralSupport.cpp b/lib/Lex/LiteralSupport.cpp index 1e7858af894..5b1c49344e8 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/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 490bd5ada62..1fd98c140e0 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -1334,8 +1334,23 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, return ExprError(); } + // Check to see whether Res is a function designator only. If it is and we + // are compiling for OpenCL, we need to return an error as this implies + // that the address of the function is being taken, which is illegal in CL. + // These can be followed by postfix-expr pieces. - return ParsePostfixExpressionSuffix(Res); + Res = ParsePostfixExpressionSuffix(Res); + if (getLangOpts().OpenCL) + if (Expr *PostfixExpr = Res.get()) { + QualType Ty = PostfixExpr->getType(); + if (!Ty.isNull() && Ty->isFunctionType()) { + Diag(PostfixExpr->getExprLoc(), + diag::err_opencl_taking_function_address_parser); + return ExprError(); + } + } + + return Res; } /// \brief Once the leading part of a postfix-expression is parsed, this diff --git a/lib/Parse/ParseStmtAsm.cpp b/lib/Parse/ParseStmtAsm.cpp index f469a064f89..142b473755d 100644 --- a/lib/Parse/ParseStmtAsm.cpp +++ b/lib/Parse/ParseStmtAsm.cpp @@ -241,9 +241,8 @@ ExprResult Parser::ParseMSAsmIdentifier(llvm::SmallVectorImpl &LineToks, ConsumeToken(); // Consume the period. IdentifierInfo *Id = Tok.getIdentifierInfo(); ConsumeToken(); // Consume the identifier. - unsigned OffsetUnused; - Result = Actions.LookupInlineAsmVarDeclField( - Result.get(), Id->getName(), OffsetUnused, Info, Tok.getLocation()); + Result = Actions.LookupInlineAsmVarDeclField(Result.get(), Id->getName(), + Info, Tok.getLocation()); } // Figure out how many tokens we are into LineToks. diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 2c5516a48d6..645074deaa0 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; } @@ -10911,12 +10910,8 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D, // from the translation unit and reattach to the current context. if (D->getLexicalDeclContext() == Context.getTranslationUnitDecl()) { // Is the decl actually in the context? - for (const auto *DI : Context.getTranslationUnitDecl()->decls()) { - if (DI == D) { - Context.getTranslationUnitDecl()->removeDecl(D); - break; - } - } + if (Context.getTranslationUnitDecl()->containsDecl(D)) + Context.getTranslationUnitDecl()->removeDecl(D); // Either way, reassign the lexical decl context to our FunctionDecl. D->setLexicalDeclContext(CurContext); } @@ -12281,16 +12276,35 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, if (!Invalid) { // If this is a use, just return the declaration we found, unless // we have attributes. - - // FIXME: In the future, return a variant or some other clue - // for the consumer of this Decl to know it doesn't own it. - // For our current ASTs this shouldn't be a problem, but will - // need to be changed with DeclGroups. - if (!Attr && - ((TUK == TUK_Reference && - (!PrevTagDecl->getFriendObjectKind() || getLangOpts().MicrosoftExt)) - || TUK == TUK_Friend)) - return PrevTagDecl; + if (TUK == TUK_Reference || TUK == TUK_Friend) { + if (Attr) { + // FIXME: Diagnose these attributes. For now, we create a new + // declaration to hold them. + } else if (TUK == TUK_Reference && + (PrevTagDecl->getFriendObjectKind() == + Decl::FOK_Undeclared || + getOwningModule(PrevDecl) != + PP.getModuleContainingLocation(KWLoc)) && + SS.isEmpty()) { + // This declaration is a reference to an existing entity, but + // has different visibility from that entity: it either makes + // a friend visible or it makes a type visible in a new module. + // In either case, create a new declaration. We only do this if + // 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())) + return PrevTagDecl; + // This is in the injected scope, create a new declaration. + } else { + return PrevTagDecl; + } + } // Diagnose attempts to redefine a tag. if (TUK == TUK_Definition) { diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 5d0c6057f54..76d0ca56c0c 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(), diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index 57a08b94f5e..1d86ca35412 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/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index e0c10e4479e..682f3692bac 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -9643,6 +9643,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 +11252,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 +11275,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 +11285,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/SemaStmtAsm.cpp b/lib/Sema/SemaStmtAsm.cpp index 0d6e0f8e41b..11a4f8bfa85 100644 --- a/lib/Sema/SemaStmtAsm.cpp +++ b/lib/Sema/SemaStmtAsm.cpp @@ -589,10 +589,8 @@ ExprResult Sema::LookupInlineAsmIdentifier(CXXScopeSpec &SS, QualType T = Result.get()->getType(); - // For now, reject dependent types. if (T->isDependentType()) { - Diag(Id.getLocStart(), diag::err_asm_incomplete_type) << T; - return ExprError(); + return Result; } // Any sort of function type is fine. @@ -674,12 +672,23 @@ bool Sema::LookupInlineAsmField(StringRef Base, StringRef Member, } ExprResult -Sema::LookupInlineAsmVarDeclField(Expr *E, StringRef Member, unsigned &Offset, +Sema::LookupInlineAsmVarDeclField(Expr *E, StringRef Member, llvm::InlineAsmIdentifierInfo &Info, SourceLocation AsmLoc) { Info.clear(); - const RecordType *RT = E->getType()->getAs(); + QualType T = E->getType(); + if (T->isDependentType()) { + DeclarationNameInfo NameInfo; + NameInfo.setLoc(AsmLoc); + NameInfo.setName(&Context.Idents.get(Member)); + return CXXDependentScopeMemberExpr::Create( + Context, E, T, /*IsArrow=*/false, AsmLoc, NestedNameSpecifierLoc(), + SourceLocation(), + /*FirstQualifierInScope=*/nullptr, NameInfo, /*TemplateArgs=*/nullptr); + } + + const RecordType *RT = T->getAs(); // FIXME: Diagnose this as field access into a scalar type. if (!RT) return ExprResult(); @@ -697,9 +706,6 @@ Sema::LookupInlineAsmVarDeclField(Expr *E, StringRef Member, unsigned &Offset, if (!FD) return ExprResult(); - Offset = (unsigned)Context.toCharUnitsFromBits(Context.getFieldOffset(FD)) - .getQuantity(); - // Make an Expr to thread through OpDecl. ExprResult Result = BuildMemberReferenceExpr( E, E->getType(), AsmLoc, /*IsArrow=*/false, CXXScopeSpec(), diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 6cc85883345..9775e4d940a 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -5503,6 +5503,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/TreeTransform.h b/lib/Sema/TreeTransform.h index e0a9653eb93..e97a2626387 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -6128,7 +6128,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 +6223,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 +6308,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(); diff --git a/lib/Serialization/ASTCommon.h b/lib/Serialization/ASTCommon.h index e59bc891f9b..64f583c9872 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 7d88a31f44a..a279475eeaf 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -4699,6 +4699,13 @@ bool ASTReader::ParseLanguageOptions(const RecordData &Record, } LangOpts.CommentOpts.ParseAllComments = Record[Idx++]; + // OpenMP offloading options. + for (unsigned N = Record[Idx++]; N; --N) { + LangOpts.OMPTargetTriples.push_back(llvm::Triple(ReadString(Record, Idx))); + } + + LangOpts.OMPHostIRFile = ReadString(Record, Idx); + return Listener.ReadLanguageOptions(LangOpts, Complain, AllowCompatibleDifferences); } diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 8fb110e4551..5bf95f878d4 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 bc678aff786..ad81ac84420 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 128935c5c73..e36e9185170 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -1323,6 +1323,13 @@ uint64_t ASTWriter::WriteControlBlock(Preprocessor &PP, } Record.push_back(LangOpts.CommentOpts.ParseAllComments); + // OpenMP offloading options. + Record.push_back(LangOpts.OMPTargetTriples.size()); + for (auto &T : LangOpts.OMPTargetTriples) + AddString(T.getTriple(), Record); + + AddString(LangOpts.OMPHostIRFile, Record); + Stream.EmitRecord(LANGUAGE_OPTIONS, Record); // Target options. @@ -4604,6 +4611,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()); @@ -5772,6 +5784,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 20ca6d6fd51..54bba282ab8 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 e52ed052d3b..000a2185f5f 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/DereferenceChecker.cpp b/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp index 5dd28320f88..f216f696ef6 100644 --- a/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp @@ -34,8 +34,7 @@ class DereferenceChecker mutable std::unique_ptr BT_null; mutable std::unique_ptr BT_undef; - void reportBug(ProgramStateRef State, const Stmt *S, CheckerContext &C, - bool IsBind = false) const; + void reportBug(ProgramStateRef State, const Stmt *S, CheckerContext &C) const; public: void checkLocation(SVal location, bool isLoad, const Stmt* S, @@ -89,8 +88,31 @@ DereferenceChecker::AddDerefSource(raw_ostream &os, } } +static const Expr *getDereferenceExpr(const Stmt *S, bool IsBind=false){ + const Expr *E = nullptr; + + // Walk through lvalue casts to get the original expression + // that syntactically caused the load. + if (const Expr *expr = dyn_cast(S)) + E = expr->IgnoreParenLValueCasts(); + + if (IsBind) { + const VarDecl *VD; + const Expr *Init; + std::tie(VD, Init) = parseAssignment(S); + if (VD && Init) + E = Init; + } + return E; +} + +static bool suppressReport(const Expr *E) { + // Do not report dereferences on memory in non-default address spaces. + return E->getType().getQualifiers().hasAddressSpace(); +} + void DereferenceChecker::reportBug(ProgramStateRef State, const Stmt *S, - CheckerContext &C, bool IsBind) const { + CheckerContext &C) const { // Generate an error node. ExplodedNode *N = C.generateErrorNode(State); if (!N) @@ -106,19 +128,6 @@ void DereferenceChecker::reportBug(ProgramStateRef State, const Stmt *S, SmallVector Ranges; - // Walk through lvalue casts to get the original expression - // that syntactically caused the load. - if (const Expr *expr = dyn_cast(S)) - S = expr->IgnoreParenLValueCasts(); - - if (IsBind) { - const VarDecl *VD; - const Expr *Init; - std::tie(VD, Init) = parseAssignment(S); - if (VD && Init) - S = Init; - } - switch (S->getStmtClass()) { case Stmt::ArraySubscriptExprClass: { os << "Array access"; @@ -209,8 +218,11 @@ void DereferenceChecker::checkLocation(SVal l, bool isLoad, const Stmt* S, // The explicit NULL case. if (nullState) { if (!notNullState) { - reportBug(nullState, S, C); - return; + const Expr *expr = getDereferenceExpr(S); + if (!suppressReport(expr)) { + reportBug(nullState, expr, C); + return; + } } // Otherwise, we have the case where the location could either be @@ -248,8 +260,11 @@ void DereferenceChecker::checkBind(SVal L, SVal V, const Stmt *S, if (StNull) { if (!StNonNull) { - reportBug(StNull, S, C, /*isBind=*/true); - return; + const Expr *expr = getDereferenceExpr(S, /*IsBind=*/true); + if (!suppressReport(expr)) { + reportBug(StNull, expr, C); + return; + } } // At this point the value could be either null or non-null. diff --git a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index 713d9fe285a..ce2c19409dc 100644 --- a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -2508,6 +2508,16 @@ bool MallocChecker::mayFreeAnyEscapedMemoryOrIsModeledExplicitly( return true; } + if (FName == "postEvent" && + FD->getQualifiedNameAsString() == "QCoreApplication::postEvent") { + return true; + } + + if (FName == "postEvent" && + FD->getQualifiedNameAsString() == "QCoreApplication::postEvent") { + return true; + } + // Handle cases where we know a buffer's /address/ can escape. // Note that the above checks handle some special cases where we know that // even though the address escapes, it's still our responsibility to free the diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index ec1310d9181..cf1e0a6a656 100644 --- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -1542,6 +1542,16 @@ LikelyFalsePositiveSuppressionBRVisitor::getEndPath(BugReporterContext &BRC, } } + // The analyzer issues a false positive when the constructor of + // std::__independent_bits_engine from algorithms is used. + if (const CXXConstructorDecl *MD = dyn_cast(D)) { + const CXXRecordDecl *CD = MD->getParent(); + if (CD->getName() == "__independent_bits_engine") { + BR.markInvalid(getTag(), nullptr); + return nullptr; + } + } + // The analyzer issues a false positive on // std::basic_string v; v.push_back(1); // and diff --git a/test/Analysis/Inputs/qt-simulator.h b/test/Analysis/Inputs/qt-simulator.h new file mode 100644 index 00000000000..d1d6c0356b7 --- /dev/null +++ b/test/Analysis/Inputs/qt-simulator.h @@ -0,0 +1,16 @@ +#pragma clang system_header + +struct QObject { +}; + +struct QEvent { + enum Type { None }; + QEvent(Type) {} +}; + +struct QCoreApplication : public QObject { + static void postEvent(QObject *receiver, QEvent *event); + static QCoreApplication *instance(); +}; + +struct QApplication : public QCoreApplication {}; diff --git a/test/Analysis/Inputs/system-header-simulator-cxx.h b/test/Analysis/Inputs/system-header-simulator-cxx.h index 35869214ed7..f9049c3ae9e 100644 --- a/test/Analysis/Inputs/system-header-simulator-cxx.h +++ b/test/Analysis/Inputs/system-header-simulator-cxx.h @@ -198,6 +198,25 @@ namespace std { storage.assignExternal(new _CharT[4]); } }; + +template +class __independent_bits_engine { +public: + // constructors and seeding functions + __independent_bits_engine(_Engine& __e, size_t __w); +}; + +template +__independent_bits_engine<_Engine, _UIntType> + ::__independent_bits_engine(_Engine& __e, size_t __w) +{ + // Fake error trigger. + // No warning is expected as we are suppressing warning coming + // out of std::basic_string. + int z = 0; + z = 5/z; +} + } void* operator new(std::size_t, const std::nothrow_t&) throw(); diff --git a/test/Analysis/inlining/stl.cpp b/test/Analysis/inlining/stl.cpp index 711c30f1031..2a8520f7671 100644 --- a/test/Analysis/inlining/stl.cpp +++ b/test/Analysis/inlining/stl.cpp @@ -47,3 +47,8 @@ void testBasicStringSuppression_assign(std::basic_string &v, const std::basic_string &v2) { v = v2; } + +class MyEngine; +void testSupprerssion_independent_bits_engine(MyEngine& e) { + std::__independent_bits_engine x(e, 64); // no-warning +} diff --git a/test/Analysis/null-deref-ps.c b/test/Analysis/null-deref-ps.c index 240e8edb13d..79b3b3a5758 100644 --- a/test/Analysis/null-deref-ps.c +++ b/test/Analysis/null-deref-ps.c @@ -311,3 +311,21 @@ int foo10595327(int b) { return *p; // no-warning return 0; } + +#define AS_ATTRIBUTE volatile __attribute__((address_space(256))) +#define _get_base() ((void * AS_ATTRIBUTE *)0) +void* test_address_space_array(unsigned long slot) { + return _get_base()[slot]; // no-warning +} +void test_address_space_condition(int AS_ATTRIBUTE *cpu_data) { + if (cpu_data == 0) { + *cpu_data = 3; // no-warning + } +} +struct X { int member; }; +int test_address_space_member() { + struct X AS_ATTRIBUTE *data = (struct X AS_ATTRIBUTE *)0UL; + int ret; + ret = data->member; // no-warning + return ret; +} diff --git a/test/Analysis/nullptr.cpp b/test/Analysis/nullptr.cpp index 17320f3b9a8..acc525e9fef 100644 --- a/test/Analysis/nullptr.cpp +++ b/test/Analysis/nullptr.cpp @@ -126,3 +126,22 @@ decltype(nullptr) returnsNullPtrType(); void fromReturnType() { ((X *)returnsNullPtrType())->f(); // expected-warning{{Called C++ object pointer is null}} } + +#define AS_ATTRIBUTE __attribute__((address_space(256))) +class AS1 { +public: + int x; + ~AS1() { + int AS_ATTRIBUTE *x = 0; + *x = 3; // no-warning + } +}; +void test_address_space_field_access() { + AS1 AS_ATTRIBUTE *pa = 0; + pa->x = 0; // no-warning +} +void test_address_space_bind() { + AS1 AS_ATTRIBUTE *pa = 0; + AS1 AS_ATTRIBUTE &r = *pa; + r.x = 0; // no-warning +} diff --git a/test/Analysis/qt_malloc.cpp b/test/Analysis/qt_malloc.cpp new file mode 100644 index 00000000000..d29835f73fa --- /dev/null +++ b/test/Analysis/qt_malloc.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.deadcode.UnreachableCode,alpha.core.CastSize,unix.Malloc,cplusplus -analyzer-store=region -verify %s +// expected-no-diagnostics +#include "Inputs/qt-simulator.h" + +void send(QObject *obj) +{ + QEvent *e1 = new QEvent(QEvent::None); + static_cast(QCoreApplication::instance())->postEvent(obj, e1); + QEvent *e2 = new QEvent(QEvent::None); + QCoreApplication::instance()->postEvent(obj, e2); + QEvent *e3 = new QEvent(QEvent::None); + QCoreApplication::postEvent(obj, e3); + QEvent *e4 = new QEvent(QEvent::None); + QApplication::postEvent(obj, e4); +} diff --git a/test/CXX/class/class.mem/p13.cpp b/test/CXX/class/class.mem/p13.cpp index 1d7b9bc8155..bc01fd4d30c 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 00000000000..31c9313cf53 --- /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/p8.cpp b/test/CXX/class/class.union/class.union.anon/p4.cpp similarity index 100% rename from test/CXX/class/class.union/p8.cpp rename to test/CXX/class/class.union/class.union.anon/p4.cpp diff --git a/test/CXX/temp/temp.res/temp.local/p6.cpp b/test/CXX/temp/temp.res/temp.local/p6.cpp index 06eb1bef7fe..843b45543fc 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/2007-04-14-FNoBuiltin.c b/test/CodeGen/2007-04-14-FNoBuiltin.c index 4d194b1e0df..b95f41c52d2 100644 --- a/test/CodeGen/2007-04-14-FNoBuiltin.c +++ b/test/CodeGen/2007-04-14-FNoBuiltin.c @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -emit-llvm %s -O2 -fno-builtin -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm %s -O2 -fno-builtin-printf -o - | FileCheck %s // Check that -fno-builtin is honored. extern int printf(const char*, ...); diff --git a/test/CodeGen/aarch64-v8.1a-neon-intrinsics.c b/test/CodeGen/aarch64-v8.1a-neon-intrinsics.c index 078b454b397..ad5d5dd4384 100644 --- a/test/CodeGen/aarch64-v8.1a-neon-intrinsics.c +++ b/test/CodeGen/aarch64-v8.1a-neon-intrinsics.c @@ -1,128 +1,198 @@ // REQUIRES: aarch64-registered-target // RUN: %clang_cc1 -triple aarch64-linux-gnu -target-feature +neon \ -// RUN: -target-feature +v8.1a -O3 -S -o - %s \ -// RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-AARCH64 +// RUN: -target-feature +v8.1a -S -emit-llvm -o - %s | FileCheck %s #include -// CHECK-AARCH64-LABEL: test_vqrdmlah_laneq_s16 +// CHECK-LABEL: test_vqrdmlah_laneq_s16 int16x4_t test_vqrdmlah_laneq_s16(int16x4_t a, int16x4_t b, int16x8_t v) { -// CHECK-AARCH64: sqrdmlah {{v[0-9]+}}.4h, {{v[0-9]+}}.4h, {{v[0-9]+}}.h[7] +// CHECK: shufflevector <8 x i16> {{%.*}}, <8 x i16> {{%.*}}, <4 x i32> +// CHECK: call <4 x i16> @llvm.aarch64.neon.sqrdmulh.v4i16(<4 x i16> {{%.*}}, <4 x i16> {{%.*}}) +// CHECK: call <4 x i16> @llvm.aarch64.neon.sqadd.v4i16(<4 x i16> {{%.*}}, <4 x i16> {{%.*}}) return vqrdmlah_laneq_s16(a, b, v, 7); } -// CHECK-AARCH64-LABEL: test_vqrdmlah_laneq_s32 +// CHECK-LABEL: test_vqrdmlah_laneq_s32 int32x2_t test_vqrdmlah_laneq_s32(int32x2_t a, int32x2_t b, int32x4_t v) { -// CHECK-AARCH64: sqrdmlah {{v[0-9]+}}.2s, {{v[0-9]+}}.2s, {{v[0-9]+}}.s[3] +// CHECK: shufflevector <4 x i32> {{%.*}}, <4 x i32> {{%.*}}, <2 x i32> +// CHECK: call <2 x i32> @llvm.aarch64.neon.sqrdmulh.v2i32(<2 x i32> {{%.*}}, <2 x i32> {{%.*}}) +// CHECK: call <2 x i32> @llvm.aarch64.neon.sqadd.v2i32(<2 x i32> {{%.*}}, <2 x i32> {{%.*}}) return vqrdmlah_laneq_s32(a, b, v, 3); } -// CHECK-AARCH64-LABEL: test_vqrdmlahq_laneq_s16 +// CHECK-LABEL: test_vqrdmlahq_laneq_s16 int16x8_t test_vqrdmlahq_laneq_s16(int16x8_t a, int16x8_t b, int16x8_t v) { -// CHECK-AARCH64: sqrdmlah {{v[0-9]+}}.8h, {{v[0-9]+}}.8h, {{v[0-9]+}}.h[7] +// CHECK: shufflevector <8 x i16> {{%.*}}, <8 x i16> {{%.*}}, <8 x i32> +// CHECK: call <8 x i16> @llvm.aarch64.neon.sqrdmulh.v8i16(<8 x i16> {{%.*}}, <8 x i16> {{%.*}}) +// CHECK: call <8 x i16> @llvm.aarch64.neon.sqadd.v8i16(<8 x i16> {{%.*}}, <8 x i16> {{%.*}}) return vqrdmlahq_laneq_s16(a, b, v, 7); } -// CHECK-AARCH64-LABEL: test_vqrdmlahq_laneq_s32 +// CHECK-LABEL: test_vqrdmlahq_laneq_s32 int32x4_t test_vqrdmlahq_laneq_s32(int32x4_t a, int32x4_t b, int32x4_t v) { -// CHECK-AARCH64: sqrdmlah {{v[0-9]+}}.4s, {{v[0-9]+}}.4s, {{v[0-9]+}}.s[3] +// CHECK: shufflevector <4 x i32> {{%.*}}, <4 x i32> {{%.*}}, <4 x i32> +// CHECK: call <4 x i32> @llvm.aarch64.neon.sqrdmulh.v4i32(<4 x i32> {{%.*}}, <4 x i32> {{%.*}}) +// CHECK: call <4 x i32> @llvm.aarch64.neon.sqadd.v4i32(<4 x i32> {{%.*}}, <4 x i32> {{%.*}}) return vqrdmlahq_laneq_s32(a, b, v, 3); } -// CHECK-AARCH64-LABEL: test_vqrdmlahh_s16 +// CHECK-LABEL: test_vqrdmlahh_s16 int16_t test_vqrdmlahh_s16(int16_t a, int16_t b, int16_t c) { -// CHECK-AARCH64: sqrdmlah {{h[0-9]+|v[0-9]+.4h}}, {{h[0-9]+|v[0-9]+.4h}}, {{h[0-9]+|v[0-9]+.4h}} +// CHECK: [[insb:%.*]] = insertelement <4 x i16> undef, i16 {{%.*}}, i64 0 +// CHECK: [[insc:%.*]] = insertelement <4 x i16> undef, i16 {{%.*}}, i64 0 +// CHECK: [[mul:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqrdmulh.v4i16(<4 x i16> [[insb]], <4 x i16> [[insc]]) +// CHECK: extractelement <4 x i16> [[mul]], i64 0 +// CHECK: [[insa:%.*]] = insertelement <4 x i16> undef, i16 {{%.*}}, i64 0 +// CHECK: [[insmul:%.*]] = insertelement <4 x i16> undef, i16 {{%.*}}, i64 0 +// CHECK: [[add:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqadd.v4i16(<4 x i16> [[insa]], <4 x i16> [[insmul]]) +// CHECK: extractelement <4 x i16> [[add]], i64 0 return vqrdmlahh_s16(a, b, c); } -// CHECK-AARCH64-LABEL: test_vqrdmlahs_s32 +// CHECK-LABEL: test_vqrdmlahs_s32 int32_t test_vqrdmlahs_s32(int32_t a, int32_t b, int32_t c) { -// CHECK-AARCH64: sqrdmlah {{s[0-9]+}}, {{s[0-9]+}}, {{s[0-9]+}} +// CHECK: call i32 @llvm.aarch64.neon.sqrdmulh.i32(i32 {{%.*}}, i32 {{%.*}}) +// CHECK: call i32 @llvm.aarch64.neon.sqadd.i32(i32 {{%.*}}, i32 {{%.*}}) return vqrdmlahs_s32(a, b, c); } -// CHECK-AARCH64-LABEL: test_vqrdmlahh_lane_s16 +// CHECK-LABEL: test_vqrdmlahh_lane_s16 int16_t test_vqrdmlahh_lane_s16(int16_t a, int16_t b, int16x4_t c) { -// CHECK-AARCH64: sqrdmlah {{h[0-9]+|v[0-9]+.4h}}, {{h[0-9]+|v[0-9]+.4h}}, {{v[0-9]+}}.h[3] +// CHECK: extractelement <4 x i16> {{%.*}}, i32 3 +// CHECK: [[insb:%.*]] = insertelement <4 x i16> undef, i16 {{%.*}}, i64 0 +// CHECK: [[insc:%.*]] = insertelement <4 x i16> undef, i16 {{%.*}}, i64 0 +// CHECK: [[mul:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqrdmulh.v4i16(<4 x i16> [[insb]], <4 x i16> [[insc]]) +// CHECK: extractelement <4 x i16> [[mul]], i64 0 +// CHECK: [[insa:%.*]] = insertelement <4 x i16> undef, i16 {{%.*}}, i64 0 +// CHECK: [[insmul:%.*]] = insertelement <4 x i16> undef, i16 {{%.*}}, i64 0 +// CHECK: [[add:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqadd.v4i16(<4 x i16> [[insa]], <4 x i16> [[insmul]]) +// CHECK: extractelement <4 x i16> [[add]], i64 0 return vqrdmlahh_lane_s16(a, b, c, 3); } -// CHECK-AARCH64-LABEL: test_vqrdmlahs_lane_s32 +// CHECK-LABEL: test_vqrdmlahs_lane_s32 int32_t test_vqrdmlahs_lane_s32(int32_t a, int32_t b, int32x2_t c) { -// CHECK-AARCH64: sqrdmlah {{s[0-9]+}}, {{s[0-9]+}}, {{v[0-9]+}}.s[1] +// CHECK: extractelement <2 x i32> {{%.*}}, i32 1 +// CHECK: call i32 @llvm.aarch64.neon.sqrdmulh.i32(i32 {{%.*}}, i32 {{%.*}}) +// CHECK: call i32 @llvm.aarch64.neon.sqadd.i32(i32 {{%.*}}, i32 {{%.*}}) return vqrdmlahs_lane_s32(a, b, c, 1); } -// CHECK-AARCH64-LABEL: test_vqrdmlahh_laneq_s16 +// CHECK-LABEL: test_vqrdmlahh_laneq_s16 int16_t test_vqrdmlahh_laneq_s16(int16_t a, int16_t b, int16x8_t c) { -// CHECK-AARCH64: sqrdmlah {{h[0-9]+|v[0-9]+.4h}}, {{h[0-9]+|v[0-9]+.4h}}, {{v[0-9]+}}.h[7] +// CHECK: extractelement <8 x i16> {{%.*}}, i32 7 +// CHECK: [[insb:%.*]] = insertelement <4 x i16> undef, i16 {{%.*}}, i64 0 +// CHECK: [[insc:%.*]] = insertelement <4 x i16> undef, i16 {{%.*}}, i64 0 +// CHECK: [[mul:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqrdmulh.v4i16(<4 x i16> [[insb]], <4 x i16> [[insc]]) +// CHECK: extractelement <4 x i16> [[mul]], i64 0 +// CHECK: [[insa:%.*]] = insertelement <4 x i16> undef, i16 {{%.*}}, i64 0 +// CHECK: [[insmul:%.*]] = insertelement <4 x i16> undef, i16 {{%.*}}, i64 0 +// CHECK: [[add:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqadd.v4i16(<4 x i16> [[insa]], <4 x i16> [[insmul]]) +// CHECK: extractelement <4 x i16> [[add]], i64 0 return vqrdmlahh_laneq_s16(a, b, c, 7); } -// CHECK-AARCH64-LABEL: test_vqrdmlahs_laneq_s32 +// CHECK-LABEL: test_vqrdmlahs_laneq_s32 int32_t test_vqrdmlahs_laneq_s32(int32_t a, int32_t b, int32x4_t c) { -// CHECK-AARCH64: sqrdmlah {{s[0-9]+}}, {{s[0-9]+}}, {{v[0-9]+}}.s[3] +// CHECK: extractelement <4 x i32> {{%.*}}, i32 3 +// CHECK: call i32 @llvm.aarch64.neon.sqrdmulh.i32(i32 {{%.*}}, i32 {{%.*}}) +// CHECK: call i32 @llvm.aarch64.neon.sqadd.i32(i32 {{%.*}}, i32 {{%.*}}) return vqrdmlahs_laneq_s32(a, b, c, 3); } -// CHECK-AARCH64-LABEL: test_vqrdmlsh_laneq_s16 +// CHECK-LABEL: test_vqrdmlsh_laneq_s16 int16x4_t test_vqrdmlsh_laneq_s16(int16x4_t a, int16x4_t b, int16x8_t v) { -// CHECK-AARCH64: sqrdmlsh {{v[0-9]+}}.4h, {{v[0-9]+}}.4h, {{v[0-9]+}}.h[7] +// CHECK: shufflevector <8 x i16> {{%.*}}, <8 x i16> {{%.*}}, <4 x i32> +// CHECK: call <4 x i16> @llvm.aarch64.neon.sqrdmulh.v4i16(<4 x i16> {{%.*}}, <4 x i16> {{%.*}}) +// CHECK: call <4 x i16> @llvm.aarch64.neon.sqsub.v4i16(<4 x i16> {{%.*}}, <4 x i16> {{%.*}}) return vqrdmlsh_laneq_s16(a, b, v, 7); } -// CHECK-AARCH64-LABEL: test_vqrdmlsh_laneq_s32 +// CHECK-LABEL: test_vqrdmlsh_laneq_s32 int32x2_t test_vqrdmlsh_laneq_s32(int32x2_t a, int32x2_t b, int32x4_t v) { -// CHECK-AARCH64: sqrdmlsh {{v[0-9]+}}.2s, {{v[0-9]+}}.2s, {{v[0-9]+}}.s[3] +// CHECK: shufflevector <4 x i32> {{%.*}}, <4 x i32> {{%.*}}, <2 x i32> +// CHECK: call <2 x i32> @llvm.aarch64.neon.sqrdmulh.v2i32(<2 x i32> {{%.*}}, <2 x i32> {{%.*}}) +// CHECK: call <2 x i32> @llvm.aarch64.neon.sqsub.v2i32(<2 x i32> {{%.*}}, <2 x i32> {{%.*}}) return vqrdmlsh_laneq_s32(a, b, v, 3); } -// CHECK-AARCH64-LABEL: test_vqrdmlshq_laneq_s16 +// CHECK-LABEL: test_vqrdmlshq_laneq_s16 int16x8_t test_vqrdmlshq_laneq_s16(int16x8_t a, int16x8_t b, int16x8_t v) { -// CHECK-AARCH64: sqrdmlsh {{v[0-9]+}}.8h, {{v[0-9]+}}.8h, {{v[0-9]+}}.h[7] +// CHECK: shufflevector <8 x i16> {{%.*}}, <8 x i16> {{%.*}}, <8 x i32> +// CHECK: call <8 x i16> @llvm.aarch64.neon.sqrdmulh.v8i16(<8 x i16> {{%.*}}, <8 x i16> {{%.*}}) +// CHECK: call <8 x i16> @llvm.aarch64.neon.sqsub.v8i16(<8 x i16> {{%.*}}, <8 x i16> {{%.*}}) return vqrdmlshq_laneq_s16(a, b, v, 7); } -// CHECK-AARCH64-LABEL: test_vqrdmlshq_laneq_s32 +// CHECK-LABEL: test_vqrdmlshq_laneq_s32 int32x4_t test_vqrdmlshq_laneq_s32(int32x4_t a, int32x4_t b, int32x4_t v) { -// CHECK-AARCH64: sqrdmlsh {{v[0-9]+}}.4s, {{v[0-9]+}}.4s, {{v[0-9]+}}.s[3] +// CHECK: shufflevector <4 x i32> {{%.*}}, <4 x i32> {{%.*}}, <4 x i32> +// CHECK: call <4 x i32> @llvm.aarch64.neon.sqrdmulh.v4i32(<4 x i32> {{%.*}}, <4 x i32> {{%.*}}) +// CHECK: call <4 x i32> @llvm.aarch64.neon.sqsub.v4i32(<4 x i32> {{%.*}}, <4 x i32> {{%.*}}) return vqrdmlshq_laneq_s32(a, b, v, 3); } -// CHECK-AARCH64-LABEL: test_vqrdmlshh_s16 +// CHECK-LABEL: test_vqrdmlshh_s16 int16_t test_vqrdmlshh_s16(int16_t a, int16_t b, int16_t c) { -// CHECK-AARCH64: sqrdmlsh {{h[0-9]+|v[0-9]+.4h}}, {{h[0-9]+|v[0-9]+.4h}}, {{h[0-9]+|v[0-9]+.4h}} +// CHECK: [[insb:%.*]] = insertelement <4 x i16> undef, i16 {{%.*}}, i64 0 +// CHECK: [[insc:%.*]] = insertelement <4 x i16> undef, i16 {{%.*}}, i64 0 +// CHECK: [[mul:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqrdmulh.v4i16(<4 x i16> [[insb]], <4 x i16> [[insc]]) +// CHECK: extractelement <4 x i16> [[mul]], i64 0 +// CHECK: [[insa:%.*]] = insertelement <4 x i16> undef, i16 {{%.*}}, i64 0 +// CHECK: [[insmul:%.*]] = insertelement <4 x i16> undef, i16 {{%.*}}, i64 0 +// CHECK: [[sub:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqsub.v4i16(<4 x i16> [[insa]], <4 x i16> [[insmul]]) +// CHECK: extractelement <4 x i16> [[sub]], i64 0 return vqrdmlshh_s16(a, b, c); } -// CHECK-AARCH64-LABEL: test_vqrdmlshs_s32 +// CHECK-LABEL: test_vqrdmlshs_s32 int32_t test_vqrdmlshs_s32(int32_t a, int32_t b, int32_t c) { -// CHECK-AARCH64: sqrdmlsh {{s[0-9]+}}, {{s[0-9]+}}, {{s[0-9]+}} +// CHECK: call i32 @llvm.aarch64.neon.sqrdmulh.i32(i32 {{%.*}}, i32 {{%.*}}) +// CHECK: call i32 @llvm.aarch64.neon.sqsub.i32(i32 {{%.*}}, i32 {{%.*}}) return vqrdmlshs_s32(a, b, c); } -// CHECK-AARCH64-LABEL: test_vqrdmlshh_lane_s16 +// CHECK-LABEL: test_vqrdmlshh_lane_s16 int16_t test_vqrdmlshh_lane_s16(int16_t a, int16_t b, int16x4_t c) { -// CHECK-AARCH64: sqrdmlsh {{h[0-9]+|v[0-9]+.4h}}, {{h[0-9]+|v[0-9]+.4h}}, {{v[0-9]+}}.h[3] +// CHECK: extractelement <4 x i16> {{%.*}}, i32 3 +// CHECK: [[insb:%.*]] = insertelement <4 x i16> undef, i16 {{%.*}}, i64 0 +// CHECK: [[insc:%.*]] = insertelement <4 x i16> undef, i16 {{%.*}}, i64 0 +// CHECK: [[mul:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqrdmulh.v4i16(<4 x i16> [[insb]], <4 x i16> [[insc]]) +// CHECK: extractelement <4 x i16> [[mul]], i64 0 +// CHECK: [[insa:%.*]] = insertelement <4 x i16> undef, i16 {{%.*}}, i64 0 +// CHECK: [[insmul:%.*]] = insertelement <4 x i16> undef, i16 {{%.*}}, i64 0 +// CHECK: [[sub:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqsub.v4i16(<4 x i16> [[insa]], <4 x i16> [[insmul]]) +// CHECK: extractelement <4 x i16> [[sub]], i64 0 return vqrdmlshh_lane_s16(a, b, c, 3); } -// CHECK-AARCH64-LABEL: test_vqrdmlshs_lane_s32 +// CHECK-LABEL: test_vqrdmlshs_lane_s32 int32_t test_vqrdmlshs_lane_s32(int32_t a, int32_t b, int32x2_t c) { -// CHECK-AARCH64: sqrdmlsh {{s[0-9]+}}, {{s[0-9]+}}, {{v[0-9]+}}.s[1] +// CHECK: extractelement <2 x i32> {{%.*}}, i32 1 +// CHECK: call i32 @llvm.aarch64.neon.sqrdmulh.i32(i32 {{%.*}}, i32 {{%.*}}) +// CHECK: call i32 @llvm.aarch64.neon.sqsub.i32(i32 {{%.*}}, i32 {{%.*}}) return vqrdmlshs_lane_s32(a, b, c, 1); } -// CHECK-AARCH64-LABEL: test_vqrdmlshh_laneq_s16 +// CHECK-LABEL: test_vqrdmlshh_laneq_s16 int16_t test_vqrdmlshh_laneq_s16(int16_t a, int16_t b, int16x8_t c) { -// CHECK-AARCH64: sqrdmlsh {{h[0-9]+|v[0-9]+.4h}}, {{h[0-9]+|v[0-9]+.4h}}, {{v[0-9]+}}.h[7] +// CHECK: extractelement <8 x i16> {{%.*}}, i32 7 +// CHECK: [[insb:%.*]] = insertelement <4 x i16> undef, i16 {{%.*}}, i64 0 +// CHECK: [[insc:%.*]] = insertelement <4 x i16> undef, i16 {{%.*}}, i64 0 +// CHECK: [[mul:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqrdmulh.v4i16(<4 x i16> [[insb]], <4 x i16> [[insc]]) +// CHECK: extractelement <4 x i16> [[mul]], i64 0 +// CHECK: [[insa:%.*]] = insertelement <4 x i16> undef, i16 {{%.*}}, i64 0 +// CHECK: [[insmul:%.*]] = insertelement <4 x i16> undef, i16 {{%.*}}, i64 0 +// CHECK: [[sub:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqsub.v4i16(<4 x i16> [[insa]], <4 x i16> [[insmul]]) +// CHECK: extractelement <4 x i16> [[sub]], i64 0 return vqrdmlshh_laneq_s16(a, b, c, 7); } -// CHECK-AARCH64-LABEL: test_vqrdmlshs_laneq_s32 +// CHECK-LABEL: test_vqrdmlshs_laneq_s32 int32_t test_vqrdmlshs_laneq_s32(int32_t a, int32_t b, int32x4_t c) { -// CHECK-AARCH64: sqrdmlsh {{s[0-9]+}}, {{s[0-9]+}}, {{v[0-9]+}}.s[3] +// CHECK: extractelement <4 x i32> {{%.*}}, i32 3 +// CHECK: call i32 @llvm.aarch64.neon.sqrdmulh.i32(i32 {{%.*}}, i32 {{%.*}}) +// CHECK: call i32 @llvm.aarch64.neon.sqsub.i32(i32 {{%.*}}, i32 {{%.*}}) return vqrdmlshs_laneq_s32(a, b, c, 3); } - diff --git a/test/CodeGen/arm-target-features.c b/test/CodeGen/arm-target-features.c index 35c0e04ff13..7829edff654 100644 --- a/test/CodeGen/arm-target-features.c +++ b/test/CodeGen/arm-target-features.c @@ -26,6 +26,7 @@ // RUN: %clang_cc1 -triple armv8-linux-gnueabi -target-cpu cortex-a53 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BASIC-V8 // RUN: %clang_cc1 -triple thumbv8-linux-gnueabihf -target-cpu cortex-a57 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BASIC-V8 // RUN: %clang_cc1 -triple thumbv8-linux-gnueabihf -target-cpu cortex-a72 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BASIC-V8 +// RUN: %clang_cc1 -triple thumbv8-linux-gnueabihf -target-cpu exynos-m1 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BASIC-V8 // CHECK-BASIC-V8: "target-features"="+crc,+crypto,+dsp,+fp-armv8,+hwdiv,+hwdiv-arm,+neon" diff --git a/test/CodeGen/arm-v8.1a-neon-intrinsics.c b/test/CodeGen/arm-v8.1a-neon-intrinsics.c index 5fe299af5f1..78888310045 100644 --- a/test/CodeGen/arm-v8.1a-neon-intrinsics.c +++ b/test/CodeGen/arm-v8.1a-neon-intrinsics.c @@ -1,122 +1,187 @@ // RUN: %clang_cc1 -triple armv8.1a-linux-gnu -target-feature +neon \ -// RUN: -O3 -S -o - %s \ +// RUN: -S -emit-llvm -o - %s \ // RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ARM + // RUN: %clang_cc1 -triple aarch64-linux-gnu -target-feature +neon \ -// RUN: -target-feature +v8.1a -O3 -S -o - %s \ +// RUN: -target-feature +v8.1a -S -emit-llvm -o - %s \ // RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-AARCH64 + // REQUIRES: arm-registered-target,aarch64-registered-target #include // CHECK-LABEL: test_vqrdmlah_s16 int16x4_t test_vqrdmlah_s16(int16x4_t a, int16x4_t b, int16x4_t c) { -// CHECK-ARM: vqrdmlah.s16 d{{[0-9]+}}, d{{[0-9]+}}, d{{[0-9]+}} -// CHECK-AARCH64: sqrdmlah {{v[0-9]+}}.4h, {{v[0-9]+}}.4h, {{v[0-9]+}}.4h +// CHECK-ARM: call <4 x i16> @llvm.arm.neon.vqrdmulh.v4i16(<4 x i16> {{%.*}}, <4 x i16> {{%.*}}) +// CHECK-ARM: call <4 x i16> @llvm.arm.neon.vqadds.v4i16(<4 x i16> {{%.*}}, <4 x i16> {{%.*}}) + +// CHECK-AARCH64: call <4 x i16> @llvm.aarch64.neon.sqrdmulh.v4i16(<4 x i16> {{%.*}}, <4 x i16> {{%.*}}) +// CHECK-AARCH64: call <4 x i16> @llvm.aarch64.neon.sqadd.v4i16(<4 x i16> {{%.*}}, <4 x i16> {{%.*}}) return vqrdmlah_s16(a, b, c); } // CHECK-LABEL: test_vqrdmlah_s32 int32x2_t test_vqrdmlah_s32(int32x2_t a, int32x2_t b, int32x2_t c) { -// CHECK-ARM: vqrdmlah.s32 d{{[0-9]+}}, d{{[0-9]+}}, d{{[0-9]+}} -// CHECK-AARCH64: sqrdmlah {{v[0-9]+}}.2s, {{v[0-9]+}}.2s, {{v[0-9]+}}.2s +// CHECK-ARM: call <2 x i32> @llvm.arm.neon.vqrdmulh.v2i32(<2 x i32> {{%.*}}, <2 x i32> {{%.*}}) +// CHECK-ARM: call <2 x i32> @llvm.arm.neon.vqadds.v2i32(<2 x i32> {{%.*}}, <2 x i32> {{%.*}}) + +// CHECK-AARCH64: call <2 x i32> @llvm.aarch64.neon.sqrdmulh.v2i32(<2 x i32> {{%.*}}, <2 x i32> {{%.*}}) +// CHECK-AARCH64: call <2 x i32> @llvm.aarch64.neon.sqadd.v2i32(<2 x i32> {{%.*}}, <2 x i32> {{%.*}}) return vqrdmlah_s32(a, b, c); } // CHECK-LABEL: test_vqrdmlahq_s16 int16x8_t test_vqrdmlahq_s16(int16x8_t a, int16x8_t b, int16x8_t c) { -// CHECK-ARM: vqrdmlah.s16 q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} -// CHECK-AARCH64: sqrdmlah {{v[0-9]+}}.8h, {{v[0-9]+}}.8h, {{v[0-9]+}}.8h +// CHECK-ARM: call <8 x i16> @llvm.arm.neon.vqrdmulh.v8i16(<8 x i16> {{%.*}}, <8 x i16> {{%.*}}) +// CHECK-ARM: call <8 x i16> @llvm.arm.neon.vqadds.v8i16(<8 x i16> {{%.*}}, <8 x i16> {{%.*}}) + +// CHECK-AARCH64: call <8 x i16> @llvm.aarch64.neon.sqrdmulh.v8i16(<8 x i16> {{%.*}}, <8 x i16> {{%.*}}) +// CHECK-AARCH64: call <8 x i16> @llvm.aarch64.neon.sqadd.v8i16(<8 x i16> {{%.*}}, <8 x i16> {{%.*}}) return vqrdmlahq_s16(a, b, c); } // CHECK-LABEL: test_vqrdmlahq_s32 int32x4_t test_vqrdmlahq_s32(int32x4_t a, int32x4_t b, int32x4_t c) { -// CHECK-ARM: vqrdmlah.s32 q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} -// CHECK-AARCH64: sqrdmlah {{v[0-9]+}}.4s, {{v[0-9]+}}.4s, {{v[0-9]+}}.4s +// CHECK-ARM: call <4 x i32> @llvm.arm.neon.vqrdmulh.v4i32(<4 x i32> {{%.*}}, <4 x i32> {{%.*}}) +// CHECK-ARM: call <4 x i32> @llvm.arm.neon.vqadds.v4i32(<4 x i32> {{%.*}}, <4 x i32> {{%.*}}) + +// CHECK-AARCH64: call <4 x i32> @llvm.aarch64.neon.sqrdmulh.v4i32(<4 x i32> {{%.*}}, <4 x i32> {{%.*}}) +// CHECK-AARCH64: call <4 x i32> @llvm.aarch64.neon.sqadd.v4i32(<4 x i32> {{%.*}}, <4 x i32> {{%.*}}) return vqrdmlahq_s32(a, b, c); } // CHECK-LABEL: test_vqrdmlah_lane_s16 int16x4_t test_vqrdmlah_lane_s16(int16x4_t a, int16x4_t b, int16x4_t c) { -// CHECK-ARM: vqrdmlah.s16 d{{[0-9]+}}, d{{[0-9]+}}, d{{[0-9]+}}[3] -// CHECK-AARCH64: sqrdmlah {{v[0-9]+}}.4h, {{v[0-9]+}}.4h, {{v[0-9]+}}.h[3] +// CHECK-ARM: shufflevector <4 x i16> {{%.*}}, <4 x i16> {{%.*}}, <4 x i32> +// CHECK-ARM: call <4 x i16> @llvm.arm.neon.vqrdmulh.v4i16(<4 x i16> {{%.*}}, <4 x i16> {{%.*}}) +// CHECK-ARM: call <4 x i16> @llvm.arm.neon.vqadds.v4i16(<4 x i16> {{%.*}}, <4 x i16> {{%.*}}) + +// CHECK-AARCH64: shufflevector <4 x i16> {{%.*}}, <4 x i16> {{%.*}}, <4 x i32> +// CHECK-AARCH64: call <4 x i16> @llvm.aarch64.neon.sqrdmulh.v4i16(<4 x i16> {{%.*}}, <4 x i16> {{%.*}}) +// CHECK-AARCH64: call <4 x i16> @llvm.aarch64.neon.sqadd.v4i16(<4 x i16> {{%.*}}, <4 x i16> {{%.*}}) return vqrdmlah_lane_s16(a, b, c, 3); } // CHECK-LABEL: test_vqrdmlah_lane_s32 int32x2_t test_vqrdmlah_lane_s32(int32x2_t a, int32x2_t b, int32x2_t c) { -// CHECK-ARM: vqrdmlah.s32 d{{[0-9]+}}, d{{[0-9]+}}, d{{[0-9]+}}[1] -// CHECK-AARCH64: sqrdmlah {{v[0-9]+}}.2s, {{v[0-9]+}}.2s, {{v[0-9]+}}.s[1] +// CHECK-ARM: shufflevector <2 x i32> {{%.*}}, <2 x i32> {{%.*}}, <2 x i32> +// CHECK-ARM: call <2 x i32> @llvm.arm.neon.vqrdmulh.v2i32(<2 x i32> {{%.*}}, <2 x i32> {{%.*}}) +// CHECK-ARM: call <2 x i32> @llvm.arm.neon.vqadds.v2i32(<2 x i32> {{%.*}}, <2 x i32> {{%.*}}) + +// CHECK-AARCH64: shufflevector <2 x i32> {{%.*}}, <2 x i32> {{%.*}}, <2 x i32> +// CHECK-AARCH64: call <2 x i32> @llvm.aarch64.neon.sqrdmulh.v2i32(<2 x i32> {{%.*}}, <2 x i32> {{%.*}}) +// CHECK-AARCH64: call <2 x i32> @llvm.aarch64.neon.sqadd.v2i32(<2 x i32> {{%.*}}, <2 x i32> {{%.*}}) return vqrdmlah_lane_s32(a, b, c, 1); } // CHECK-LABEL: test_vqrdmlahq_lane_s16 int16x8_t test_vqrdmlahq_lane_s16(int16x8_t a, int16x8_t b, int16x4_t c) { -// CHECK-ARM: vqrdmlah.s16 q{{[0-9]+}}, q{{[0-9]+}}, d{{[0-9]+}}[3] -// CHECK-AARCH64: sqrdmlah {{v[0-9]+}}.8h, {{v[0-9]+}}.8h, {{v[0-9]+}}.h[3] +// CHECK-ARM: shufflevector <4 x i16> {{%.*}}, <4 x i16> {{%.*}}, <8 x i32> +// CHECK-ARM: call <8 x i16> @llvm.arm.neon.vqrdmulh.v8i16(<8 x i16> {{%.*}}, <8 x i16> {{%.*}}) +// CHECK-ARM: call <8 x i16> @llvm.arm.neon.vqadds.v8i16(<8 x i16> {{%.*}}, <8 x i16> {{%.*}}) + +// CHECK-AARCH64: shufflevector <4 x i16> {{%.*}}, <4 x i16> {{%.*}}, <8 x i32> +// CHECK-AARCH64: call <8 x i16> @llvm.aarch64.neon.sqrdmulh.v8i16(<8 x i16> {{%.*}}, <8 x i16> {{%.*}}) +// CHECK-AARCH64: call <8 x i16> @llvm.aarch64.neon.sqadd.v8i16(<8 x i16> {{%.*}}, <8 x i16> {{%.*}}) return vqrdmlahq_lane_s16(a, b, c, 3); } // CHECK-LABEL: test_vqrdmlahq_lane_s32 int32x4_t test_vqrdmlahq_lane_s32(int32x4_t a, int32x4_t b, int32x2_t c) { -// CHECK-ARM: vqrdmlah.s32 q{{[0-9]+}}, q{{[0-9]+}}, d{{[0-9]+}}[1] -// CHECK-AARCH64: sqrdmlah {{v[0-9]+}}.4s, {{v[0-9]+}}.4s, {{v[0-9]+}}.s[1] +// CHECK-ARM: shufflevector <2 x i32> {{%.*}}, <2 x i32> {{%.*}}, <4 x i32> +// CHECK-ARM: call <4 x i32> @llvm.arm.neon.vqrdmulh.v4i32(<4 x i32> {{%.*}}, <4 x i32> {{%.*}}) +// CHECK-ARM: call <4 x i32> @llvm.arm.neon.vqadds.v4i32(<4 x i32> {{%.*}}, <4 x i32> {{%.*}}) + +// CHECK-AARCH64: shufflevector <2 x i32> {{%.*}}, <2 x i32> {{%.*}}, <4 x i32> +// CHECK-AARCH64: call <4 x i32> @llvm.aarch64.neon.sqrdmulh.v4i32(<4 x i32> {{%.*}}, <4 x i32> {{%.*}}) +// CHECK-AARCH64: call <4 x i32> @llvm.aarch64.neon.sqadd.v4i32(<4 x i32> {{%.*}}, <4 x i32> {{%.*}}) return vqrdmlahq_lane_s32(a, b, c, 1); } // CHECK-LABEL: test_vqrdmlsh_s16 int16x4_t test_vqrdmlsh_s16(int16x4_t a, int16x4_t b, int16x4_t c) { -// CHECK-ARM: vqrdmlsh.s16 d{{[0-9]+}}, d{{[0-9]+}}, d{{[0-9]+}} -// CHECK-AARCH64: sqrdmlsh {{v[0-9]+}}.4h, {{v[0-9]+}}.4h, {{v[0-9]+}}.4h +// CHECK-ARM: call <4 x i16> @llvm.arm.neon.vqrdmulh.v4i16(<4 x i16> {{%.*}}, <4 x i16> {{%.*}}) +// CHECK-ARM: call <4 x i16> @llvm.arm.neon.vqsubs.v4i16(<4 x i16> {{%.*}}, <4 x i16> {{%.*}}) + +// CHECK-AARCH64: call <4 x i16> @llvm.aarch64.neon.sqrdmulh.v4i16(<4 x i16> {{%.*}}, <4 x i16> {{%.*}}) +// CHECK-AARCH64: call <4 x i16> @llvm.aarch64.neon.sqsub.v4i16(<4 x i16> {{%.*}}, <4 x i16> {{%.*}}) return vqrdmlsh_s16(a, b, c); } // CHECK-LABEL: test_vqrdmlsh_s32 int32x2_t test_vqrdmlsh_s32(int32x2_t a, int32x2_t b, int32x2_t c) { -// CHECK-ARM: vqrdmlsh.s32 d{{[0-9]+}}, d{{[0-9]+}}, d{{[0-9]+}} -// CHECK-AARCH64: sqrdmlsh {{v[0-9]+}}.2s, {{v[0-9]+}}.2s, {{v[0-9]+}}.2s +// CHECK-ARM: call <2 x i32> @llvm.arm.neon.vqrdmulh.v2i32(<2 x i32> {{%.*}}, <2 x i32> {{%.*}}) +// CHECK-ARM: call <2 x i32> @llvm.arm.neon.vqsubs.v2i32(<2 x i32> {{%.*}}, <2 x i32> {{%.*}}) + +// CHECK-AARCH64: call <2 x i32> @llvm.aarch64.neon.sqrdmulh.v2i32(<2 x i32> {{%.*}}, <2 x i32> {{%.*}}) +// CHECK-AARCH64: call <2 x i32> @llvm.aarch64.neon.sqsub.v2i32(<2 x i32> {{%.*}}, <2 x i32> {{%.*}}) return vqrdmlsh_s32(a, b, c); } // CHECK-LABEL: test_vqrdmlshq_s16 int16x8_t test_vqrdmlshq_s16(int16x8_t a, int16x8_t b, int16x8_t c) { -// CHECK-ARM: vqrdmlsh.s16 q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} -// CHECK-AARCH64: sqrdmlsh {{v[0-9]+}}.8h, {{v[0-9]+}}.8h, {{v[0-9]+}}.8h +// CHECK-ARM: call <8 x i16> @llvm.arm.neon.vqrdmulh.v8i16(<8 x i16> {{%.*}}, <8 x i16> {{%.*}}) +// CHECK-ARM: call <8 x i16> @llvm.arm.neon.vqsubs.v8i16(<8 x i16> {{%.*}}, <8 x i16> {{%.*}}) + +// CHECK-AARCH64: call <8 x i16> @llvm.aarch64.neon.sqrdmulh.v8i16(<8 x i16> {{%.*}}, <8 x i16> {{%.*}}) +// CHECK-AARCH64: call <8 x i16> @llvm.aarch64.neon.sqsub.v8i16(<8 x i16> {{%.*}}, <8 x i16> {{%.*}}) return vqrdmlshq_s16(a, b, c); } // CHECK-LABEL: test_vqrdmlshq_s32 int32x4_t test_vqrdmlshq_s32(int32x4_t a, int32x4_t b, int32x4_t c) { -// CHECK-ARM: vqrdmlsh.s32 q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} -// CHECK-AARCH64: sqrdmlsh {{v[0-9]+}}.4s, {{v[0-9]+}}.4s, {{v[0-9]+}}.4s +// CHECK-ARM: call <4 x i32> @llvm.arm.neon.vqrdmulh.v4i32(<4 x i32> {{%.*}}, <4 x i32> {{%.*}}) +// CHECK-ARM: call <4 x i32> @llvm.arm.neon.vqsubs.v4i32(<4 x i32> {{%.*}}, <4 x i32> {{%.*}}) + +// CHECK-AARCH64: call <4 x i32> @llvm.aarch64.neon.sqrdmulh.v4i32(<4 x i32> {{%.*}}, <4 x i32> {{%.*}}) +// CHECK-AARCH64: call <4 x i32> @llvm.aarch64.neon.sqsub.v4i32(<4 x i32> {{%.*}}, <4 x i32> {{%.*}}) return vqrdmlshq_s32(a, b, c); } // CHECK-LABEL: test_vqrdmlsh_lane_s16 int16x4_t test_vqrdmlsh_lane_s16(int16x4_t a, int16x4_t b, int16x4_t c) { -// CHECK-ARM: vqrdmlsh.s16 d{{[0-9]+}}, d{{[0-9]+}}, d{{[0-9]+}}[3] -// CHECK-AARCH64: sqrdmlsh {{v[0-9]+}}.4h, {{v[0-9]+}}.4h, {{v[0-9]+}}.h[3] +// CHECK-ARM: shufflevector <4 x i16> {{%.*}}, <4 x i16> {{%.*}}, <4 x i32> +// CHECK-ARM: call <4 x i16> @llvm.arm.neon.vqrdmulh.v4i16(<4 x i16> {{%.*}}, <4 x i16> {{%.*}}) +// CHECK-ARM: call <4 x i16> @llvm.arm.neon.vqsubs.v4i16(<4 x i16> {{%.*}}, <4 x i16> {{%.*}}) + +// CHECK-AARCH64: shufflevector <4 x i16> {{%.*}}, <4 x i16> {{%.*}}, <4 x i32> +// CHECK-AARCH64: call <4 x i16> @llvm.aarch64.neon.sqrdmulh.v4i16(<4 x i16> {{%.*}}, <4 x i16> {{%.*}}) +// CHECK-AARCH64: call <4 x i16> @llvm.aarch64.neon.sqsub.v4i16(<4 x i16> {{%.*}}, <4 x i16> {{%.*}}) return vqrdmlsh_lane_s16(a, b, c, 3); } // CHECK-LABEL: test_vqrdmlsh_lane_s32 int32x2_t test_vqrdmlsh_lane_s32(int32x2_t a, int32x2_t b, int32x2_t c) { -// CHECK-ARM: vqrdmlsh.s32 d{{[0-9]+}}, d{{[0-9]+}}, d{{[0-9]+}}[1] -// CHECK-AARCH64: sqrdmlsh {{v[0-9]+}}.2s, {{v[0-9]+}}.2s, {{v[0-9]+}}.s[1] +// CHECK-ARM: shufflevector <2 x i32> {{%.*}}, <2 x i32> {{%.*}}, <2 x i32> +// CHECK-ARM: call <2 x i32> @llvm.arm.neon.vqrdmulh.v2i32(<2 x i32> {{%.*}}, <2 x i32> {{%.*}}) +// CHECK-ARM: call <2 x i32> @llvm.arm.neon.vqsubs.v2i32(<2 x i32> {{%.*}}, <2 x i32> {{%.*}}) + +// CHECK-AARCH64: shufflevector <2 x i32> {{%.*}}, <2 x i32> {{%.*}}, <2 x i32> +// CHECK-AARCH64: call <2 x i32> @llvm.aarch64.neon.sqrdmulh.v2i32(<2 x i32> {{%.*}}, <2 x i32> {{%.*}}) +// CHECK-AARCH64: call <2 x i32> @llvm.aarch64.neon.sqsub.v2i32(<2 x i32> {{%.*}}, <2 x i32> {{%.*}}) return vqrdmlsh_lane_s32(a, b, c, 1); } // CHECK-LABEL: test_vqrdmlshq_lane_s16 int16x8_t test_vqrdmlshq_lane_s16(int16x8_t a, int16x8_t b, int16x4_t c) { -// CHECK-ARM: vqrdmlsh.s16 q{{[0-9]+}}, q{{[0-9]+}}, d{{[0-9]+}}[3] -// CHECK-AARCH64: sqrdmlsh {{v[0-9]+}}.8h, {{v[0-9]+}}.8h, {{v[0-9]+}}.h[3] +// CHECK-ARM: shufflevector <4 x i16> {{%.*}}, <4 x i16> {{%.*}}, <8 x i32> +// CHECK-ARM: call <8 x i16> @llvm.arm.neon.vqrdmulh.v8i16(<8 x i16> {{%.*}}, <8 x i16> {{%.*}}) +// CHECK-ARM: call <8 x i16> @llvm.arm.neon.vqsubs.v8i16(<8 x i16> {{%.*}}, <8 x i16> {{%.*}}) + +// CHECK-AARCH64: shufflevector <4 x i16> {{%.*}}, <4 x i16> {{%.*}}, <8 x i32> +// CHECK-AARCH64: call <8 x i16> @llvm.aarch64.neon.sqrdmulh.v8i16(<8 x i16> {{%.*}}, <8 x i16> {{%.*}}) +// CHECK-AARCH64: call <8 x i16> @llvm.aarch64.neon.sqsub.v8i16(<8 x i16> {{%.*}}, <8 x i16> {{%.*}}) return vqrdmlshq_lane_s16(a, b, c, 3); } // CHECK-LABEL: test_vqrdmlshq_lane_s32 int32x4_t test_vqrdmlshq_lane_s32(int32x4_t a, int32x4_t b, int32x2_t c) { -// CHECK-ARM: vqrdmlsh.s32 q{{[0-9]+}}, q{{[0-9]+}}, d{{[0-9]+}}[1] -// CHECK-AARCH64: sqrdmlsh {{v[0-9]+}}.4s, {{v[0-9]+}}.4s, {{v[0-9]+}}.s[1] +// CHECK-ARM: shufflevector <2 x i32> {{%.*}}, <2 x i32> {{%.*}}, <4 x i32> +// CHECK-ARM: call <4 x i32> @llvm.arm.neon.vqrdmulh.v4i32(<4 x i32> {{%.*}}, <4 x i32> {{%.*}}) +// CHECK-ARM: call <4 x i32> @llvm.arm.neon.vqsubs.v4i32(<4 x i32> {{%.*}}, <4 x i32> {{%.*}}) + +// CHECK-AARCH64: shufflevector <2 x i32> {{%.*}}, <2 x i32> {{%.*}}, <4 x i32> +// CHECK-AARCH64: call <4 x i32> @llvm.aarch64.neon.sqrdmulh.v4i32(<4 x i32> {{%.*}}, <4 x i32> {{%.*}}) +// CHECK-AARCH64: call <4 x i32> @llvm.aarch64.neon.sqsub.v4i32(<4 x i32> {{%.*}}, <4 x i32> {{%.*}}) return vqrdmlshq_lane_s32(a, b, c, 1); } - diff --git a/test/CodeGen/libcalls-complex.c b/test/CodeGen/libcalls-complex.c index 22c97b6a7b3..43b70550d8b 100644 --- a/test/CodeGen/libcalls-complex.c +++ b/test/CodeGen/libcalls-complex.c @@ -1,4 +1,7 @@ // RUN: %clang_cc1 -fno-builtin -emit-llvm -o - %s -triple i386-unknown-unknown | FileCheck -check-prefix CHECK-YES %s +// RUN: %clang_cc1 -fno-builtin-crealf -fno-builtin-creal -fno-builtin-creall \ +// RUN: -fno-builtin-cimagf -fno-builtin-cimag -fno-builtin-cimagl -emit-llvm \ +// RUN: -o - %s -triple i386-unknown-unknown | FileCheck -check-prefix CHECK-YES %s // RUN: %clang_cc1 -emit-llvm -o - %s -triple i386-unknown-unknown | FileCheck -check-prefix CHECK-NO %s extern float crealf(float _Complex); diff --git a/test/CodeGen/libcalls-fno-builtin.c b/test/CodeGen/libcalls-fno-builtin.c index e7f3ef7b41d..bc6a4302b01 100644 --- a/test/CodeGen/libcalls-fno-builtin.c +++ b/test/CodeGen/libcalls-fno-builtin.c @@ -1,4 +1,11 @@ // RUN: %clang_cc1 -S -O3 -fno-builtin -o - %s | FileCheck %s +// RUN: %clang_cc1 -S -O3 -fno-builtin-ceil -fno-builtin-copysign -fno-builtin-cos \ +// RUN: -fno-builtin-fabs -fno-builtin-floor -fno-builtin-strcat -fno-builtin-strncat \ +// RUN: -fno-builtin-strchr -fno-builtin-strrchr -fno-builtin-strcmp -fno-builtin-strncmp \ +// RUN: -fno-builtin-strcpy -fno-builtin-stpcpy -fno-builtin-strncpy -fno-builtin-strlen \ +// RUN: -fno-builtin-strpbrk -fno-builtin-strspn -fno-builtin-strtod -fno-builtin-strtof \ +// RUN: -fno-builtin-strtold -fno-builtin-strtol -fno-builtin-strtoll -fno-builtin-strtoul \ +// RUN: -fno-builtin-strtoull -o - %s | FileCheck %s // rdar://10551066 typedef __SIZE_TYPE__ size_t; diff --git a/test/CodeGen/nobuiltin.c b/test/CodeGen/nobuiltin.c index 0a8e8bb4b6d..7cc8164c6f1 100644 --- a/test/CodeGen/nobuiltin.c +++ b/test/CodeGen/nobuiltin.c @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -fno-builtin -O1 -S -o - %s | FileCheck %s +// RUN: %clang_cc1 -fno-builtin-memset -O1 -S -o - %s | FileCheck -check-prefix=MEMSET %s void PR13497() { char content[2]; @@ -6,3 +7,11 @@ void PR13497() { // CHECK: __strcpy_chk __builtin___strcpy_chk(content, "", 1); } + +void PR4941(char *s) { + // Make sure we don't optimize this loop to a memset(). + // MEMSET-LABEL: PR4941: + // MEMSET-NOT: memset + for (unsigned i = 0; i < 8192; ++i) + s[i] = 0; +} diff --git a/test/CodeGen/target-data.c b/test/CodeGen/target-data.c index 56ef330da06..909a8e2ff73 100644 --- a/test/CodeGen/target-data.c +++ b/test/CodeGen/target-data.c @@ -84,11 +84,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/ms-inline-asm-fields.cpp b/test/CodeGenCXX/ms-inline-asm-fields.cpp index a78d511485a..6f329330bda 100644 --- a/test/CodeGenCXX/ms-inline-asm-fields.cpp +++ b/test/CodeGenCXX/ms-inline-asm-fields.cpp @@ -29,3 +29,28 @@ extern "C" int test_namespace_global() { __asm mov eax, asdf::a_global.a3.b2 } +template +struct make_storage_type { + struct type { + struct B { + int a; + int x; + } b; + }; +}; + +template +struct msvc_dcas_x86 { + typedef typename make_storage_type::type storage_type; + void store() __asm("PR26001") { + storage_type p; + __asm mov edx, p.b.x; + } +}; + +template void msvc_dcas_x86::store(); +// CHECK: define weak_odr void @"\01PR26001"( +// CHECK: %[[P:.*]] = alloca %"struct.make_storage_type::type", align 4 +// CHECK: %[[B:.*]] = getelementptr inbounds %"struct.make_storage_type::type", %"struct.make_storage_type::type"* %[[P]], i32 0, i32 0 +// CHECK: %[[X:.*]] = getelementptr inbounds %"struct.make_storage_type::type::B", %"struct.make_storage_type::type::B"* %[[B]], i32 0, i32 1 +// CHECK: call void asm sideeffect inteldialect "mov edx, dword ptr $0", "*m,~{edx},~{dirflag},~{fpsr},~{flags}"(i32* %[[X]]) diff --git a/test/CodeGenCXX/pass-object-size.cpp b/test/CodeGenCXX/pass-object-size.cpp index 254669b9762..2c7f9742a8e 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/Driver/aarch64-cpus.c b/test/Driver/aarch64-cpus.c index 6355c248182..7b0fac44247 100644 --- a/test/Driver/aarch64-cpus.c +++ b/test/Driver/aarch64-cpus.c @@ -74,6 +74,20 @@ // RUN: %clang -target arm64 -mlittle-endian -mtune=cortex-a72 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-CA72 %s // ARM64-CA72: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "cortex-a72" +// RUN: %clang -target aarch64 -mcpu=exynos-m1 -### -c %s 2>&1 | FileCheck -check-prefix=M1 %s +// RUN: %clang -target aarch64 -mlittle-endian -mcpu=exynos-m1 -### -c %s 2>&1 | FileCheck -check-prefix=M1 %s +// RUN: %clang -target aarch64_be -mlittle-endian -mcpu=exynos-m1 -### -c %s 2>&1 | FileCheck -check-prefix=M1 %s +// RUN: %clang -target aarch64 -mtune=exynos-m1 -### -c %s 2>&1 | FileCheck -check-prefix=M1 %s +// RUN: %clang -target aarch64 -mlittle-endian -mtune=exynos-m1 -### -c %s 2>&1 | FileCheck -check-prefix=M1 %s +// RUN: %clang -target aarch64_be -mlittle-endian -mtune=exynos-m1 -### -c %s 2>&1 | FileCheck -check-prefix=M1 %s +// M1: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "exynos-m1" + +// RUN: %clang -target arm64 -mcpu=exynos-m1 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-M1 %s +// RUN: %clang -target arm64 -mlittle-endian -mcpu=exynos-m1 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-M1 %s +// RUN: %clang -target arm64 -mtune=exynos-m1 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-M1 %s +// RUN: %clang -target arm64 -mlittle-endian -mtune=exynos-m1 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-M1 %s +// ARM64-M1: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "exynos-m1" + // RUN: %clang -target aarch64_be -### -c %s 2>&1 | FileCheck -check-prefix=GENERIC-BE %s // RUN: %clang -target aarch64 -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=GENERIC-BE %s // RUN: %clang -target aarch64_be -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=GENERIC-BE %s @@ -111,6 +125,14 @@ // RUN: %clang -target aarch64_be -mbig-endian -mtune=cortex-a72 -### -c %s 2>&1 | FileCheck -check-prefix=CA72-BE %s // CA72-BE: "-cc1"{{.*}} "-triple" "aarch64_be{{.*}}" "-target-cpu" "cortex-a72" +// RUN: %clang -target aarch64_be -mcpu=exynos-m1 -### -c %s 2>&1 | FileCheck -check-prefix=M1-BE %s +// RUN: %clang -target aarch64 -mbig-endian -mcpu=exynos-m1 -### -c %s 2>&1 | FileCheck -check-prefix=M1-BE %s +// RUN: %clang -target aarch64_be -mbig-endian -mcpu=exynos-m1 -### -c %s 2>&1 | FileCheck -check-prefix=M1-BE %s +// RUN: %clang -target aarch64_be -mtune=exynos-m1 -### -c %s 2>&1 | FileCheck -check-prefix=M1-BE %s +// RUN: %clang -target aarch64 -mbig-endian -mtune=exynos-m1 -### -c %s 2>&1 | FileCheck -check-prefix=M1-BE %s +// RUN: %clang -target aarch64_be -mbig-endian -mtune=exynos-m1 -### -c %s 2>&1 | FileCheck -check-prefix=M1-BE %s +// M1-BE: "-cc1"{{.*}} "-triple" "aarch64_be{{.*}}" "-target-cpu" "exynos-m1" + // RUN: %clang -target aarch64 -mcpu=cortex-a57 -mtune=cortex-a53 -### -c %s 2>&1 | FileCheck -check-prefix=MCPU-MTUNE %s // RUN: %clang -target aarch64 -mtune=cortex-a53 -mcpu=cortex-a57 -### -c %s 2>&1 | FileCheck -check-prefix=MCPU-MTUNE %s // RUN: %clang -target aarch64 -mcpu=cortex-a72 -mtune=cortex-a53 -### -c %s 2>&1 | FileCheck -check-prefix=MCPU-MTUNE %s diff --git a/test/Driver/arm-cortex-cpus.c b/test/Driver/arm-cortex-cpus.c index c0492efb91d..6a4d2d631b3 100644 --- a/test/Driver/arm-cortex-cpus.c +++ b/test/Driver/arm-cortex-cpus.c @@ -398,40 +398,48 @@ // RUN: %clang -target arm -mcpu=cortex-a53 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s // RUN: %clang -target arm -mcpu=cortex-a57 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s // RUN: %clang -target arm -mcpu=cortex-a72 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s +// RUN: %clang -target arm -mcpu=exynos-m1 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s // RUN: %clang -target arm -mcpu=cortex-a35 -mlittle-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s // RUN: %clang -target arm -mcpu=cortex-a53 -mlittle-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s // RUN: %clang -target arm -mcpu=cortex-a57 -mlittle-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s // RUN: %clang -target arm -mcpu=cortex-a72 -mlittle-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s +// RUN: %clang -target arm -mcpu=exynos-m1 -mlittle-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s // CHECK-CPUV8A: "-cc1"{{.*}} "-triple" "armv8-{{.*}} // RUN: %clang -target armeb -mcpu=cortex-a35 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s // RUN: %clang -target armeb -mcpu=cortex-a53 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s // RUN: %clang -target armeb -mcpu=cortex-a57 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s // RUN: %clang -target armeb -mcpu=cortex-a72 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s +// RUN: %clang -target armeb -mcpu=exynos-m1 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s // RUN: %clang -target arm -mcpu=cortex-a35 -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s // RUN: %clang -target arm -mcpu=cortex-a53 -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s // RUN: %clang -target arm -mcpu=cortex-a57 -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s // RUN: %clang -target arm -mcpu=cortex-a72 -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s +// RUN: %clang -target arm -mcpu=exynos-m1 -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s // CHECK-BE-CPUV8A: "-cc1"{{.*}} "-triple" "armebv8-{{.*}} // RUN: %clang -target arm -mcpu=cortex-a35 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s // RUN: %clang -target arm -mcpu=cortex-a53 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s // RUN: %clang -target arm -mcpu=cortex-a57 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s // RUN: %clang -target arm -mcpu=cortex-a72 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s +// RUN: %clang -target arm -mcpu=exynos-m1 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s // RUN: %clang -target arm -mcpu=cortex-a35 -mlittle-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s // RUN: %clang -target arm -mcpu=cortex-a53 -mlittle-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s // RUN: %clang -target arm -mcpu=cortex-a57 -mlittle-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s // RUN: %clang -target arm -mcpu=cortex-a72 -mlittle-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s +// RUN: %clang -target arm -mcpu=exynos-m1 -mlittle-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s // CHECK-CPUV8A-THUMB: "-cc1"{{.*}} "-triple" "thumbv8-{{.*}} // RUN: %clang -target armeb -mcpu=cortex-a35 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s // RUN: %clang -target armeb -mcpu=cortex-a53 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s // RUN: %clang -target armeb -mcpu=cortex-a57 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s // RUN: %clang -target armeb -mcpu=cortex-a72 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s +// RUN: %clang -target armeb -mcpu=exynos-m1 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s // RUN: %clang -target arm -mcpu=cortex-a35 -mbig-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s // RUN: %clang -target arm -mcpu=cortex-a53 -mbig-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s // RUN: %clang -target arm -mcpu=cortex-a57 -mbig-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s // RUN: %clang -target arm -mcpu=cortex-a72 -mbig-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s +// RUN: %clang -target arm -mcpu=exynos-m1 -mbig-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s // CHECK-BE-CPUV8A-THUMB: "-cc1"{{.*}} "-triple" "thumbebv8-{{.*}} // ================== Check whether -mcpu accepts mixed-case values. diff --git a/test/Driver/arm-no-movt.c b/test/Driver/arm-no-movt.c index 1107cf8ff89..69085931c3f 100644 --- a/test/Driver/arm-no-movt.c +++ b/test/Driver/arm-no-movt.c @@ -4,11 +4,11 @@ // RUN: %clang -target armv7-apple-darwin -mkernel -### %s 2>&1 \ // RUN: | FileCheck %s -check-prefix CHECK-KERNEL -// RUN: %clang -target armv7-gnueabi-freebsd11 -### %s 2>&1 \ -// RUN: | FileCheck %s -check-prefix CHECK-FREEBSD +// RUN: %clang -target armv7-none-gnueabi -mno-movt -### %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix CHECK-NO-MOVT // CHECK-DEFAULT-NOT: "-target-feature" "+no-movt" // CHECK-KERNEL: "-target-feature" "+no-movt" -// CHECK-FREEBSD: "-target-feature" "+no-movt" +// CHECK-NO-MOVT: "-target-feature" "+no-movt" diff --git a/test/Driver/debug-options.c b/test/Driver/debug-options.c index e160b7fd326..72d0136a8c4 100644 --- a/test/Driver/debug-options.c +++ b/test/Driver/debug-options.c @@ -169,3 +169,8 @@ // NOCI-NOT: "-dwarf-column-info" // // GEXTREFS: "-dwarf-ext-refs" "-fmodule-format=obj" "-debug-info-kind={{standalone|limited}}" + +// RUN: not %clang -cc1 -debug-info-kind=watkind 2>&1 | FileCheck -check-prefix=BADSTRING1 %s +// BADSTRING1: error: invalid value 'watkind' in '-debug-info-kind=watkind' +// RUN: not %clang -cc1 -debugger-tuning=gmodal 2>&1 | FileCheck -check-prefix=BADSTRING2 %s +// BADSTRING2: error: invalid value 'gmodal' in '-debugger-tuning=gmodal' diff --git a/test/Driver/fortran.f95 b/test/Driver/fortran.f95 index 9334cbec442..47c6e7b50c9 100644 --- a/test/Driver/fortran.f95 +++ b/test/Driver/fortran.f95 @@ -1,9 +1,21 @@ // Check that the clang driver can invoke gcc to compile Fortran. // RUN: %clang -target x86_64-unknown-linux-gnu -integrated-as -c %s -### 2>&1 \ -// RUN: | FileCheck %s -// CHECK: gcc -// CHECK: "-S" -// CHECK: "-x" "f95" -// CHECK: clang -// CHECK: "-cc1as" +// RUN: | FileCheck --check-prefix=CHECK-OBJECT %s +// CHECK-OBJECT: gcc +// CHECK-OBJECT: "-c" +// CHECK-OBJECT: "-x" "f95" +// CHECK-OBJECT-NOT: cc1as + +// RUN: %clang -target x86_64-unknown-linux-gnu -integrated-as -S %s -### 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-ASM %s +// CHECK-ASM: gcc +// 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 4892bd92ac6..d28e432b1e1 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/instrprof-ld.c b/test/Driver/instrprof-ld.c index b3ba12ee434..05f65d61460 100644 --- a/test/Driver/instrprof-ld.c +++ b/test/Driver/instrprof-ld.c @@ -105,3 +105,19 @@ // // CHECK-WATCHOS-ARMV7: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}" // CHECK-WATCHOS-ARMV7: "{{.*}}/Inputs/resource_dir{{/|\\\\}}lib{{/|\\\\}}darwin{{/|\\\\}}libclang_rt.profile_watchos.a" +// +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -target i386-pc-win32 -fprofile-instr-generate \ +// RUN: -resource-dir=%S/Inputs/resource_dir \ +// RUN: | FileCheck --check-prefix=CHECK-WINDOWS-I386 %s +// +// CHECK-WINDOWS-I386: "{{.*}}link{{(.exe)?}}" +// CHECK-WINDOWS-I386: "{{.*}}clang_rt.profile-i386.lib" +// +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -target x86_64-pc-win32 -fprofile-instr-generate \ +// RUN: -resource-dir=%S/Inputs/resource_dir \ +// RUN: | FileCheck --check-prefix=CHECK-WINDOWS-X86-64 %s +// +// CHECK-WINDOWS-X86-64: "{{.*}}link{{(.exe)?}}" +// CHECK-WINDOWS-X86-64: "{{.*}}clang_rt.profile-x86_64.lib" diff --git a/test/Driver/ps4-analyzer-defaults.cpp b/test/Driver/ps4-analyzer-defaults.cpp new file mode 100644 index 00000000000..f5aacc616e8 --- /dev/null +++ b/test/Driver/ps4-analyzer-defaults.cpp @@ -0,0 +1,33 @@ +// Check that the default analyzer checkers for PS4 are: +// core +// cplusplus +// deadcode +// nullability +// unix +// Excluding: +// unix.API +// unix.Vfork + +// Check for expected checkers +// RUN: %clang -target x86_64-scei-ps4 --analyze %s -### 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-PS4-POS-CHECKERS +// +// Negative check for unexpected checkers +// RUN: %clang -target x86_64-scei-ps4 --analyze %s -### 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-PS4-NEG-CHECKERS +// +// Check for all unix checkers except API and Vfork +// RUN: %clang -target x86_64-scei-ps4 --analyze %s -### 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-PS4-UNIX-CHECKERS + +// CHECK-PS4-POS-CHECKERS-DAG: analyzer-checker=core +// CHECK-PS4-POS-CHECKERS-DAG: analyzer-checker=cplusplus +// CHECK-PS4-POS-CHECKERS-DAG: analyzer-checker=deadcode +// CHECK-PS4-POS-CHECKERS-DAG: analyzer-checker=nullability +// +// CHECK-PS4-NEG-CHECKERS-NOT: analyzer-checker={{osx|security}} +// +// CHECK-PS4-UNIX-CHECKERS: analyzer-checker=unix +// CHECK-PS4-UNIX-CHECKERS-DAG: analyzer-disable-checker=unix.API +// CHECK-PS4-UNIX-CHECKERS-DAG: analyzer-disable-checker=unix.Vfork +// CHECK-PS4-UNIX-CHECKERS-NOT: analyzer-checker=unix.{{API|Vfork}} diff --git a/test/Driver/wasm-toolchain.c b/test/Driver/wasm-toolchain.c index 4d707a0f6c8..a51da0891c8 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 +// -fvisibilt=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 c47428796dc..3f44d93df57 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 c33f4e56a65..6162759884a 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/cindex-test-inclusions.c b/test/Index/cindex-test-inclusions.c index 9c7de2e2c63..b85cd24f074 100644 --- a/test/Index/cindex-test-inclusions.c +++ b/test/Index/cindex-test-inclusions.c @@ -11,3 +11,14 @@ // CHECK: included by: // CHECK: include_test.h:1:10 // CHECK: cindex-test-inclusions.c:3:10 + +// RUN: env CINDEXTEST_EDITING=1 c-index-test -test-inclusion-stack-source %s 2>&1 | FileCheck -check-prefix=REPARSE %s +// REPARSE: include_test_2.h +// REPARSE: included by: +// REPARSE: include_test.h:1:10 +// REPARSE: cindex-test-inclusions.c:3:10 +// REPARSE: include_test.h +// REPARSE: included by: +// REPARSE: cindex-test-inclusions.c:3:10 +// REPARSE: cindex-test-inclusions.c +// REPARSE: included by: diff --git a/test/Index/print-type-declaration.cpp b/test/Index/print-type-declaration.cpp new file mode 100644 index 00000000000..31c0a73fcd0 --- /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-print-char-literal.cpp b/test/Misc/ast-print-char-literal.cpp new file mode 100644 index 00000000000..bb5daa2444d --- /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 6ef4445cb97..c84c691993f 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,9 @@ namespace DebugCXX { typedef A B; void foo(B) {} } + +// Virtual class with a forward declaration. +class FwdVirtual; +class FwdVirtual { + virtual ~FwdVirtual() {} +}; diff --git a/test/Modules/ModuleDebugInfo.cpp b/test/Modules/ModuleDebugInfo.cpp index 81192cb3e93..ca66a318925 100644 --- a/test/Modules/ModuleDebugInfo.cpp +++ b/test/Modules/ModuleDebugInfo.cpp @@ -7,13 +7,11 @@ // RUN: rm -rf %t // RUN: %clang_cc1 -triple %itanium_abi_triple -x objective-c++ -std=c++11 -debug-info-kind=limited -fmodules -fmodule-format=obj -fimplicit-module-maps -DMODULES -fmodules-cache-path=%t %s -I %S/Inputs -I %t -emit-llvm -o %t.ll -mllvm -debug-only=pchcontainer &>%t-mod.ll // RUN: cat %t-mod.ll | FileCheck %s -// RUN: cat %t-mod.ll | FileCheck --check-prefix=CHECK-NEG %s // RUN: cat %t-mod.ll | FileCheck --check-prefix=CHECK-DWO %s // PCH: // RUN: %clang_cc1 -triple %itanium_abi_triple -x c++ -std=c++11 -emit-pch -fmodule-format=obj -I %S/Inputs -o %t.pch %S/Inputs/DebugCXX.h -mllvm -debug-only=pchcontainer &>%t-pch.ll // RUN: cat %t-pch.ll | FileCheck %s -// RUN: cat %t-mod.ll | FileCheck --check-prefix=CHECK-NEG %s #ifdef MODULES @import DebugCXX; @@ -23,22 +21,32 @@ // 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" diff --git a/test/Modules/tag-injection.cpp b/test/Modules/tag-injection.cpp new file mode 100644 index 00000000000..75c8b5fecdb --- /dev/null +++ b/test/Modules/tag-injection.cpp @@ -0,0 +1,22 @@ +// RUN: rm -rf %t +// RUN: mkdir %t +// RUN: touch %t/a.h +// RUN: echo 'struct X {};' > %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 -fmodules-local-submodule-visibility -std=c++11 + +#include "a.h" + +struct A { + // This use of 'struct X' makes the declaration (but not definition) of X visible. + virtual void f(struct X *p); +}; + +namespace N { + struct B : A { + void f(struct X *q) override; + }; +} + +X x; // expected-error {{definition of 'X' must be imported from module 'X.b' before it is required}} +// expected-note@b.h:1 {{here}} diff --git a/test/OpenMP/target_codegen.cpp b/test/OpenMP/target_codegen.cpp index bcefa2419dd..c2e08d67b84 100644 --- a/test/OpenMP/target_codegen.cpp +++ b/test/OpenMP/target_codegen.cpp @@ -1,15 +1,32 @@ -// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 -// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 -// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 -// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 +// Test host codegen. +// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -omptargets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 +// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -omptargets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -omptargets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 +// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -omptargets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 +// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -omptargets=i386-pc-linux-gnu -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -omptargets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 + +// Test target codegen - host bc file has to be created first. +// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -omptargets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc +// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -omptargets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -omp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64 +// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -omptargets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -omp-host-ir-file-path %t-ppc-host.bc -o %t %s +// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -omptargets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -omp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64 +// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -omptargets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc +// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -omptargets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -omp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32 +// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -omptargets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -omp-host-ir-file-path %t-x86-host.bc -o %t %s +// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -omptargets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -omp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32 + // expected-no-diagnostics #ifndef HEADER #define HEADER // CHECK-DAG: [[TT:%.+]] = type { i64, i8 } // CHECK-DAG: [[S1:%.+]] = type { double } +// CHECK-DAG: [[ENTTY:%.+]] = type { i8*, i8*, i[[SZ:32|64]] } +// CHECK-DAG: [[DEVTY:%.+]] = type { i8*, i8*, [[ENTTY]]*, [[ENTTY]]* } +// CHECK-DAG: [[DSCTY:%.+]] = type { i32, [[DEVTY]]*, [[ENTTY]]*, [[ENTTY]]* } + +// TCHECK: [[ENTTY:%.+]] = type { i8*, i8*, i{{32|64}} } // We have 8 target regions, but only 7 that actually will generate offloading // code, only 6 will have mapped arguments, and only 4 have all-constant map @@ -33,6 +50,27 @@ // CHECK-DAG: @{{.*}} = private constant i8 0 // CHECK-DAG: @{{.*}} = private constant i8 0 +// TCHECK: @{{.+}} = constant [[ENTTY]] +// TCHECK: @{{.+}} = constant [[ENTTY]] +// TCHECK: @{{.+}} = constant [[ENTTY]] +// TCHECK: @{{.+}} = constant [[ENTTY]] +// TCHECK: @{{.+}} = constant [[ENTTY]] +// TCHECK: @{{.+}} = constant [[ENTTY]] +// TCHECK: @{{.+}} = constant [[ENTTY]] +// TCHECK-NOT: @{{.+}} = constant [[ENTTY]] + +// Check if offloading descriptor is created. +// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]] +// CHECK: [[ENTEND:@.+]] = external constant [[ENTTY]] +// CHECK: [[DEVBEGIN:@.+]] = external constant i8 +// CHECK: [[DEVEND:@.+]] = external constant i8 +// CHECK: [[IMAGES:@.+]] = internal unnamed_addr constant [1 x [[DEVTY]]] [{{.+}} { i8* [[DEVBEGIN]], i8* [[DEVEND]], [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }] +// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 1, [[DEVTY]]* getelementptr inbounds ([1 x [[DEVTY]]], [1 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] } + +// Check target registration is registered as a Ctor. +// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* [[REGFN:@.+]] to void ()*), i8* null }] + + template struct TT{ tx X; diff --git a/test/OpenMP/target_codegen_global_capture.cpp b/test/OpenMP/target_codegen_global_capture.cpp index 29469cdf71e..211a3cc884b 100644 --- a/test/OpenMP/target_codegen_global_capture.cpp +++ b/test/OpenMP/target_codegen_global_capture.cpp @@ -1,9 +1,9 @@ -// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 -// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 -// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 -// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 +// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -omptargets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 +// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -omptargets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -omptargets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 +// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -omptargets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 +// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -omptargets=i386-pc-linux-gnu -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -omptargets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 // expected-no-diagnostics #ifndef HEADER #define HEADER diff --git a/test/OpenMP/target_codegen_registration.cpp b/test/OpenMP/target_codegen_registration.cpp new file mode 100644 index 00000000000..7d515bb64d9 --- /dev/null +++ b/test/OpenMP/target_codegen_registration.cpp @@ -0,0 +1,437 @@ +// Test host codegen. +// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -omptargets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -omptargets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -omptargets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -omptargets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -omptargets=i386-pc-linux-gnu -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -omptargets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s + +// Test target codegen - host bc file has to be created first. +// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -omptargets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc +// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -omptargets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -omp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s -check-prefix=TCHECK +// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -omptargets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -omp-host-ir-file-path %t-ppc-host.bc -o %t %s +// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -omptargets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -omp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s -check-prefix=TCHECK +// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -omptargets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc +// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -omptargets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -omp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s -check-prefix=TCHECK +// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -omptargets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -omp-host-ir-file-path %t-x86-host.bc -o %t %s +// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -omptargets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -omp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s -check-prefix=TCHECK + +// Check that no target code is emmitted if no omptests flag was provided. +// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s -check-prefix=CHECK-NTARGET + +// expected-no-diagnostics +#ifndef HEADER +#define HEADER + +// CHECK-DAG: [[SA:%.+]] = type { [4 x i32] } +// CHECK-DAG: [[SB:%.+]] = type { [8 x i32] } +// CHECK-DAG: [[SC:%.+]] = type { [16 x i32] } +// CHECK-DAG: [[SD:%.+]] = type { [32 x i32] } +// CHECK-DAG: [[SE:%.+]] = type { [64 x i32] } +// CHECK-DAG: [[ST1:%.+]] = type { [228 x i32] } +// CHECK-DAG: [[ST2:%.+]] = type { [1128 x i32] } +// CHECK-DAG: [[ENTTY:%.+]] = type { i8*, i8*, i[[SZ:32|64]] } +// CHECK-DAG: [[DEVTY:%.+]] = type { i8*, i8*, [[ENTTY]]*, [[ENTTY]]* } +// CHECK-DAG: [[DSCTY:%.+]] = type { i32, [[DEVTY]]*, [[ENTTY]]*, [[ENTTY]]* } + +// TCHECK: [[ENTTY:%.+]] = type { i8*, i8*, i[[SZ:32|64]] } + +// CHECK-DAG: [[A1:@.+]] = internal global [[SA]] +// CHECK-DAG: [[A2:@.+]] = global [[SA]] +// CHECK-DAG: [[B1:@.+]] = global [[SB]] +// CHECK-DAG: [[B2:@.+]] = global [[SB]] +// CHECK-DAG: [[C1:@.+]] = internal global [[SC]] +// CHECK-DAG: [[D1:@.+]] = global [[SD]] +// CHECK-DAG: [[E1:@.+]] = global [[SE]] +// CHECK-DAG: [[T1:@.+]] = global [[ST1]] +// CHECK-DAG: [[T2:@.+]] = global [[ST2]] + +// CHECK-NTARGET-DAG: [[SA:%.+]] = type { [4 x i32] } +// CHECK-NTARGET-DAG: [[SB:%.+]] = type { [8 x i32] } +// CHECK-NTARGET-DAG: [[SC:%.+]] = type { [16 x i32] } +// CHECK-NTARGET-DAG: [[SD:%.+]] = type { [32 x i32] } +// CHECK-NTARGET-DAG: [[SE:%.+]] = type { [64 x i32] } +// CHECK-NTARGET-DAG: [[ST1:%.+]] = type { [228 x i32] } +// CHECK-NTARGET-DAG: [[ST2:%.+]] = type { [1128 x i32] } +// CHECK-NTARGET-NOT: type { i8*, +// CHECK-NTARGET-NOT: type { i32, + +// We have 7 target regions + +// CHECK-DAG: {{@.+}} = private constant i8 0 +// TCHECK-NOT: {{@.+}} = private constant i8 0 +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i32] [i32 128] +// CHECK-DAG: {{@.+}} = private constant i8 0 +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i32] [i32 128] +// CHECK-DAG: {{@.+}} = private constant i8 0 +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i32] [i32 128] +// CHECK-DAG: {{@.+}} = private constant i8 0 +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i32] [i32 128] +// CHECK-DAG: {{@.+}} = private constant i8 0 +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i32] [i32 128] +// CHECK-DAG: {{@.+}} = private constant i8 0 +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i32] [i32 128] +// CHECK-DAG: {{@.+}} = private constant i8 0 +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i32] [i32 128] +// CHECK-DAG: {{@.+}} = private constant i8 0 +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i32] [i32 128] +// CHECK-DAG: {{@.+}} = private constant i8 0 +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i32] [i32 128] +// CHECK-DAG: {{@.+}} = private constant i8 0 +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i32] [i32 128] +// CHECK-DAG: {{@.+}} = private constant i8 0 +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i32] [i32 128] +// CHECK-DAG: {{@.+}} = private constant i8 0 +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i32] [i32 128] + +// CHECK-NTARGET-NOT: private constant i8 0 +// CHECK-NTARGET-NOT: private unnamed_addr constant [1 x i + +// CHECK-DAG: [[NAMEPTR1:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME1:\.omp_offloading\.[0-9a-f]+\.[0-9a-f]+\._Z.+\.l[0-9]+\.c[0-9]+]]\00" +// CHECK-DAG: [[ENTRY1:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0 }, section ".omp_offloading.entries", align 1 +// CHECK-DAG: [[NAMEPTR2:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME2:.+]]\00" +// CHECK-DAG: [[ENTRY2:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0 }, section ".omp_offloading.entries", align 1 +// CHECK-DAG: [[NAMEPTR3:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME3:.+]]\00" +// CHECK-DAG: [[ENTRY3:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0 }, section ".omp_offloading.entries", align 1 +// CHECK-DAG: [[NAMEPTR4:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME4:.+]]\00" +// CHECK-DAG: [[ENTRY4:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0 }, section ".omp_offloading.entries", align 1 +// CHECK-DAG: [[NAMEPTR5:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME5:.+]]\00" +// CHECK-DAG: [[ENTRY5:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0 }, section ".omp_offloading.entries", align 1 +// CHECK-DAG: [[NAMEPTR6:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME6:.+]]\00" +// CHECK-DAG: [[ENTRY6:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0 }, section ".omp_offloading.entries", align 1 +// CHECK-DAG: [[NAMEPTR7:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME7:.+]]\00" +// CHECK-DAG: [[ENTRY7:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0 }, section ".omp_offloading.entries", align 1 +// CHECK-DAG: [[NAMEPTR8:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME8:.+]]\00" +// CHECK-DAG: [[ENTRY8:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0 }, section ".omp_offloading.entries", align 1 +// CHECK-DAG: [[NAMEPTR9:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME9:.+]]\00" +// CHECK-DAG: [[ENTRY9:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0 }, section ".omp_offloading.entries", align 1 +// CHECK-DAG: [[NAMEPTR10:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME10:.+]]\00" +// CHECK-DAG: [[ENTRY10:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0 }, section ".omp_offloading.entries", align 1 +// CHECK-DAG: [[NAMEPTR11:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME11:.+]]\00" +// CHECK-DAG: [[ENTRY11:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0 }, section ".omp_offloading.entries", align 1 +// CHECK-DAG: [[NAMEPTR12:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME12:.+]]\00" +// CHECK-DAG: [[ENTRY12:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0 }, section ".omp_offloading.entries", align 1 + +// TCHECK-DAG: [[NAMEPTR1:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME1:\.omp_offloading\.[0-9a-f]+\.[0-9a-f]+\._Z.+\.l[0-9]+\.c[0-9]+]]\00" +// TCHECK-DAG: [[ENTRY1:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0 }, section ".omp_offloading.entries", align 1 +// TCHECK-DAG: [[NAMEPTR2:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME2:.+]]\00" +// TCHECK-DAG: [[ENTRY2:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0 }, section ".omp_offloading.entries", align 1 +// TCHECK-DAG: [[NAMEPTR3:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME3:.+]]\00" +// TCHECK-DAG: [[ENTRY3:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0 }, section ".omp_offloading.entries", align 1 +// TCHECK-DAG: [[NAMEPTR4:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME4:.+]]\00" +// TCHECK-DAG: [[ENTRY4:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0 }, section ".omp_offloading.entries", align 1 +// TCHECK-DAG: [[NAMEPTR5:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME5:.+]]\00" +// TCHECK-DAG: [[ENTRY5:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0 }, section ".omp_offloading.entries", align 1 +// TCHECK-DAG: [[NAMEPTR6:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME6:.+]]\00" +// TCHECK-DAG: [[ENTRY6:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0 }, section ".omp_offloading.entries", align 1 +// TCHECK-DAG: [[NAMEPTR7:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME7:.+]]\00" +// TCHECK-DAG: [[ENTRY7:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0 }, section ".omp_offloading.entries", align 1 +// TCHECK-DAG: [[NAMEPTR8:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME8:.+]]\00" +// TCHECK-DAG: [[ENTRY8:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0 }, section ".omp_offloading.entries", align 1 +// TCHECK-DAG: [[NAMEPTR9:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME9:.+]]\00" +// TCHECK-DAG: [[ENTRY9:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0 }, section ".omp_offloading.entries", align 1 +// TCHECK-DAG: [[NAMEPTR10:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME10:.+]]\00" +// TCHECK-DAG: [[ENTRY10:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0 }, section ".omp_offloading.entries", align 1 +// TCHECK-DAG: [[NAMEPTR11:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME11:.+]]\00" +// TCHECK-DAG: [[ENTRY11:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0 }, section ".omp_offloading.entries", align 1 +// TCHECK-DAG: [[NAMEPTR12:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME12:.+]]\00" +// TCHECK-DAG: [[ENTRY12:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0 }, section ".omp_offloading.entries", align 1 + +// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]] +// CHECK: [[ENTEND:@.+]] = external constant [[ENTTY]] +// CHECK: [[DEVBEGIN:@.+]] = external constant i8 +// CHECK: [[DEVEND:@.+]] = external constant i8 +// CHECK: [[IMAGES:@.+]] = internal unnamed_addr constant [1 x [[DEVTY]]] [{{.+}} { i8* [[DEVBEGIN]], i8* [[DEVEND]], [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }] +// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 1, [[DEVTY]]* getelementptr inbounds ([1 x [[DEVTY]]], [1 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] } + +// We have 4 initializers, one for the 500 priority, another one for 501, or more for the default priority, and the last one for the offloading registration function. +// CHECK: @llvm.global_ctors = appending global [4 x { i32, void ()*, i8* }] [ +// CHECK-SAME: { i32, void ()*, i8* } { i32 500, void ()* [[P500:@[^,]+]], i8* null }, +// CHECK-SAME: { i32, void ()*, i8* } { i32 501, void ()* [[P501:@[^,]+]], i8* null }, +// CHECK-SAME: { i32, void ()*, i8* } { i32 65535, void ()* [[PMAX:@[^,]+]], i8* null }, +// CHECK-SAME: { i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* [[REGFN:@.+]] to void ()*), i8* null }] + +// CHECK-NTARGET: @llvm.global_ctors = appending global [3 x { i32, void ()*, i8* }] [ + +extern int *R; + +struct SA { + int arr[4]; + void foo() { + int a = *R; + a += 1; + *R = a; + } + SA() { + int a = *R; + a += 2; + *R = a; + } + ~SA() { + int a = *R; + a += 3; + *R = a; + } +}; + +struct SB { + int arr[8]; + void foo() { + int a = *R; + #pragma omp target + a += 4; + *R = a; + } + SB() { + int a = *R; + a += 5; + *R = a; + } + ~SB() { + int a = *R; + a += 6; + *R = a; + } +}; + +struct SC { + int arr[16]; + void foo() { + int a = *R; + a += 7; + *R = a; + } + SC() { + int a = *R; + #pragma omp target + a += 8; + *R = a; + } + ~SC() { + int a = *R; + a += 9; + *R = a; + } +}; + +struct SD { + int arr[32]; + void foo() { + int a = *R; + a += 10; + *R = a; + } + SD() { + int a = *R; + a += 11; + *R = a; + } + ~SD() { + int a = *R; + #pragma omp target + a += 12; + *R = a; + } +}; + +struct SE { + int arr[64]; + void foo() { + int a = *R; + #pragma omp target if(0) + a += 13; + *R = a; + } + SE() { + int a = *R; + #pragma omp target + a += 14; + *R = a; + } + ~SE() { + int a = *R; + #pragma omp target + a += 15; + *R = a; + } +}; + +template +struct ST { + int arr[128 + x]; + void foo() { + int a = *R; + #pragma omp target + a += 16 + x; + *R = a; + } + ST() { + int a = *R; + #pragma omp target + a += 17 + x; + *R = a; + } + ~ST() { + int a = *R; + #pragma omp target + a += 18 + x; + *R = a; + } +}; + +// We have to make sure we us all the target regions: +//CHECK-DAG: define internal void @[[NAME1]]( +//CHECK-DAG: call void @[[NAME1]]( +//CHECK-DAG: define internal void @[[NAME2]]( +//CHECK-DAG: call void @[[NAME2]]( +//CHECK-DAG: define internal void @[[NAME3]]( +//CHECK-DAG: call void @[[NAME3]]( +//CHECK-DAG: define internal void @[[NAME4]]( +//CHECK-DAG: call void @[[NAME4]]( +//CHECK-DAG: define internal void @[[NAME5]]( +//CHECK-DAG: call void @[[NAME5]]( +//CHECK-DAG: define internal void @[[NAME6]]( +//CHECK-DAG: call void @[[NAME6]]( +//CHECK-DAG: define internal void @[[NAME7]]( +//CHECK-DAG: call void @[[NAME7]]( +//CHECK-DAG: define internal void @[[NAME8]]( +//CHECK-DAG: call void @[[NAME8]]( +//CHECK-DAG: define internal void @[[NAME9]]( +//CHECK-DAG: call void @[[NAME9]]( +//CHECK-DAG: define internal void @[[NAME10]]( +//CHECK-DAG: call void @[[NAME10]]( +//CHECK-DAG: define internal void @[[NAME11]]( +//CHECK-DAG: call void @[[NAME11]]( +//CHECK-DAG: define internal void @[[NAME12]]( +//CHECK-DAG: call void @[[NAME12]]( + +//TCHECK-DAG: define void @[[NAME1]]( +//TCHECK-DAG: define void @[[NAME2]]( +//TCHECK-DAG: define void @[[NAME3]]( +//TCHECK-DAG: define void @[[NAME4]]( +//TCHECK-DAG: define void @[[NAME5]]( +//TCHECK-DAG: define void @[[NAME6]]( +//TCHECK-DAG: define void @[[NAME7]]( +//TCHECK-DAG: define void @[[NAME8]]( +//TCHECK-DAG: define void @[[NAME9]]( +//TCHECK-DAG: define void @[[NAME10]]( +//TCHECK-DAG: define void @[[NAME11]]( +//TCHECK-DAG: define void @[[NAME12]]( + +// CHECK-NTARGET-NOT: __tgt_target +// CHECK-NTARGET-NOT: __tgt_register_lib +// CHECK-NTARGET-NOT: __tgt_unregister_lib + +// TCHECK-NOT: __tgt_target +// TCHECK-NOT: __tgt_register_lib +// TCHECK-NOT: __tgt_unregister_lib + +// We have 2 initializers with priority 500 +//CHECK: define internal void [[P500]]( +//CHECK: call void @{{.+}}() +//CHECK: call void @{{.+}}() +//CHECK-NOT: call void @{{.+}}() +//CHECK: ret void + +// We have 1 initializers with priority 501 +//CHECK: define internal void [[P501]]( +//CHECK: call void @{{.+}}() +//CHECK-NOT: call void @{{.+}}() +//CHECK: ret void + +// We have 6 initializers with default priority +//CHECK: define internal void [[PMAX]]( +//CHECK: call void @{{.+}}() +//CHECK: call void @{{.+}}() +//CHECK: call void @{{.+}}() +//CHECK: call void @{{.+}}() +//CHECK: call void @{{.+}}() +//CHECK: call void @{{.+}}() +//CHECK-NOT: call void @{{.+}}() +//CHECK: ret void + +// Check registration and unregistration + +//CHECK: define internal void [[UNREGFN:@.+]](i8*) +//CHECK: call i32 @__tgt_unregister_lib([[DSCTY]]* [[DESC]]) +//CHECK: ret void +//CHECK: declare i32 @__tgt_unregister_lib([[DSCTY]]*) + +//CHECK: define internal void [[REGFN]](i8*) +//CHECK: call i32 @__tgt_register_lib([[DSCTY]]* [[DESC]]) +//CHECK: call i32 @__cxa_atexit(void (i8*)* [[UNREGFN]], i8* bitcast ([[DSCTY]]* [[DESC]] to i8*), +//CHECK: ret void +//CHECK: declare i32 @__tgt_register_lib([[DSCTY]]*) + +static __attribute__((init_priority(500))) SA a1; +SA a2; +SB __attribute__((init_priority(500))) b1; +SB __attribute__((init_priority(501))) b2; +static SC c1; +SD d1; +SE e1; +ST<100> t1; +ST<1000> t2; + + +int bar(int a){ + int r = a; + + a1.foo(); + a2.foo(); + b1.foo(); + b2.foo(); + c1.foo(); + d1.foo(); + e1.foo(); + t1.foo(); + t2.foo(); + + #pragma omp target + ++r; + + return r + *R; +} + +// 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 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 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 new file mode 100644 index 00000000000..ab7a469aba4 --- /dev/null +++ b/test/OpenMP/target_codegen_registration_naming.cpp @@ -0,0 +1,66 @@ +// Test host codegen. +// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -omptargets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -omptargets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -omptargets=powerpc64le-ibm-linux-gnu -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -omptargets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -omptargets=i386-pc-linux-gnu -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -omptargets=i386-pc-linux-gnu -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s + +// Test target codegen - host bc file has to be created first. +// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -omptargets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc +// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -omptargets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -omp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s -check-prefix=TCHECK +// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -std=c++11 -triple powerpc64le-unknown-unknown -omptargets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -omp-host-ir-file-path %t-ppc-host.bc -o %t %s +// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -omptargets=powerpc64le-ibm-linux-gnu -fopenmp-is-device -omp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s -check-prefix=TCHECK +// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -omptargets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc +// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -omptargets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -omp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s -check-prefix=TCHECK +// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -omptargets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -omp-host-ir-file-path %t-x86-host.bc -o %t %s +// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -omptargets=i386-pc-linux-gnu -fopenmp-is-device -omp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s -check-prefix=TCHECK + +// expected-no-diagnostics +#ifndef HEADER +#define HEADER + +// CHECK: [[CA:%.+]] = type { i32* } + +// CHECK: define {{.*}}i32 @[[NNAME:.+]](i32 {{.*}}%{{.+}}) +int nested(int a){ + // CHECK: call void @.omp_offloading.[[FILEID:[0-9a-f]+\.[0-9a-f]+]].[[NNAME]].l[[T1L:[0-9]+]].c[[T1C:[0-9]+]]( + #pragma omp target + ++a; + + // CHECK: call void @"[[LNAME:.+]]"([[CA]]* + auto F = [&](){ + #pragma omp parallel + { + #pragma omp target + ++a; + } + }; + + F(); + + return a; +} + +// CHECK: define {{.*}}void @.omp_offloading.[[FILEID]].[[NNAME]].l[[T1L]].c[[T1C]]( +// TCHECK: define {{.*}}void @.omp_offloading.[[FILEID:[0-9a-f]+\.[0-9a-f]+]].[[NNAME:.+]].l[[T1L:[0-9]+]].c[[T1C:[0-9]+]]( + +// CHECK: define {{.*}}void @"[[LNAME]]"( +// CHECK: call void {{.*}}@__kmpc_fork_call{{.+}}[[PNAME:@.+]] to + +// CHECK: define {{.*}}void [[PNAME]]( +// CHECK: call void @.omp_offloading.[[FILEID]].[[NNAME]].l[[T2L:[0-9]+]].c[[T2C:[0-9]+]]( + +// CHECK: define {{.*}}void @.omp_offloading.[[FILEID]].[[NNAME]].l[[T2L]].c[[T2C]]( +// TCHECK: define {{.*}}void @.omp_offloading.[[FILEID]].[[NNAME:.+]].l[[T2L:[0-9]+]].c[[T2C:[0-9]+]]( + + +// 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]+}}} + +// 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]+}}} +#endif diff --git a/test/OpenMP/target_map_codegen.cpp b/test/OpenMP/target_map_codegen.cpp index 2b24c829640..942cc4c09fd 100644 --- a/test/OpenMP/target_map_codegen.cpp +++ b/test/OpenMP/target_map_codegen.cpp @@ -7,12 +7,12 @@ /// ///==========================================================================/// -// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-64 -// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-64 -// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32 -// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32 +// RUN: %clang_cc1 -DCK1 -verify -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-64 +// RUN: %clang_cc1 -DCK1 -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-64 +// RUN: %clang_cc1 -DCK1 -verify -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32 +// RUN: %clang_cc1 -DCK1 -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32 #ifdef CK1 // CK1-DAG: [[SIZES:@.+]] = {{.+}}constant [1 x i[[sz:64|32]]] [i{{64|32}} 4] @@ -52,12 +52,12 @@ void implicit_maps_integer (int a){ #endif ///==========================================================================/// -// RUN: %clang_cc1 -DCK2 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-64 -// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-64 -// RUN: %clang_cc1 -DCK2 -verify -fopenmp -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32 -// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32 +// RUN: %clang_cc1 -DCK2 -verify -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-64 +// RUN: %clang_cc1 -DCK2 -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-64 +// RUN: %clang_cc1 -DCK2 -verify -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32 +// RUN: %clang_cc1 -DCK2 -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32 #ifdef CK2 // CK2-DAG: [[SIZES:@.+]] = {{.+}}constant [1 x i[[sz:64|32]]] [i{{64|32}} 4] @@ -101,12 +101,12 @@ void implicit_maps_integer_reference (int a){ #endif ///==========================================================================/// -// RUN: %clang_cc1 -DCK3 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK3 --check-prefix CK3-64 -// RUN: %clang_cc1 -DCK3 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK3 --check-prefix CK3-64 -// RUN: %clang_cc1 -DCK3 -verify -fopenmp -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK3 --check-prefix CK3-32 -// RUN: %clang_cc1 -DCK3 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK3 --check-prefix CK3-32 +// RUN: %clang_cc1 -DCK3 -verify -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK3 --check-prefix CK3-64 +// RUN: %clang_cc1 -DCK3 -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK3 --check-prefix CK3-64 +// RUN: %clang_cc1 -DCK3 -verify -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK3 --check-prefix CK3-32 +// RUN: %clang_cc1 -DCK3 -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK3 --check-prefix CK3-32 #ifdef CK3 // CK3-DAG: [[SIZES:@.+]] = {{.+}}constant [1 x i[[sz:64|32]]] [i{{64|32}} 4] @@ -145,12 +145,12 @@ void implicit_maps_parameter (int a){ #endif ///==========================================================================/// -// RUN: %clang_cc1 -DCK4 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK4 --check-prefix CK4-64 -// RUN: %clang_cc1 -DCK4 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK4 --check-prefix CK4-64 -// RUN: %clang_cc1 -DCK4 -verify -fopenmp -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK4 --check-prefix CK4-32 -// RUN: %clang_cc1 -DCK4 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK4 --check-prefix CK4-32 +// RUN: %clang_cc1 -DCK4 -verify -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK4 --check-prefix CK4-64 +// RUN: %clang_cc1 -DCK4 -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK4 --check-prefix CK4-64 +// RUN: %clang_cc1 -DCK4 -verify -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK4 --check-prefix CK4-32 +// RUN: %clang_cc1 -DCK4 -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK4 --check-prefix CK4-32 #ifdef CK4 // CK4-DAG: [[SIZES:@.+]] = {{.+}}constant [1 x i[[sz:64|32]]] [i{{64|32}} 4] @@ -201,12 +201,12 @@ void implicit_maps_nested_integer (int a){ // CK4: define internal void [[KERNELP2]](i32* {{[^,]+}}, i32* {{[^,]+}}, i32* {{[^,]+}}) #endif ///==========================================================================/// -// RUN: %clang_cc1 -DCK5 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK5 --check-prefix CK5-64 -// RUN: %clang_cc1 -DCK5 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK5 --check-prefix CK5-64 -// RUN: %clang_cc1 -DCK5 -verify -fopenmp -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK5 --check-prefix CK5-32 -// RUN: %clang_cc1 -DCK5 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK5 --check-prefix CK5-32 +// RUN: %clang_cc1 -DCK5 -verify -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK5 --check-prefix CK5-64 +// RUN: %clang_cc1 -DCK5 -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK5 --check-prefix CK5-64 +// RUN: %clang_cc1 -DCK5 -verify -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK5 --check-prefix CK5-32 +// RUN: %clang_cc1 -DCK5 -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK5 --check-prefix CK5-32 #ifdef CK5 // CK5-DAG: [[SIZES:@.+]] = {{.+}}constant [1 x i[[sz:64|32]]] [i{{64|32}} 4] @@ -252,12 +252,12 @@ void implicit_maps_nested_integer_and_enum (int a){ #endif ///==========================================================================/// -// RUN: %clang_cc1 -DCK6 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK6 --check-prefix CK6-64 -// RUN: %clang_cc1 -DCK6 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK6 --check-prefix CK6-64 -// RUN: %clang_cc1 -DCK6 -verify -fopenmp -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK6 --check-prefix CK6-32 -// RUN: %clang_cc1 -DCK6 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK6 --check-prefix CK6-32 +// RUN: %clang_cc1 -DCK6 -verify -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK6 --check-prefix CK6-64 +// RUN: %clang_cc1 -DCK6 -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK6 --check-prefix CK6-64 +// RUN: %clang_cc1 -DCK6 -verify -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK6 --check-prefix CK6-32 +// RUN: %clang_cc1 -DCK6 -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK6 --check-prefix CK6-32 #ifdef CK6 // CK6-DAG: [[GBL:@Gi]] = global i32 0 // CK6-DAG: [[SIZES:@.+]] = {{.+}}constant [1 x i[[sz:64|32]]] [i{{64|32}} 4] @@ -298,12 +298,12 @@ void implicit_maps_host_global (int a){ #endif ///==========================================================================/// -// RUN: %clang_cc1 -DCK7 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK7 --check-prefix CK7-64 -// RUN: %clang_cc1 -DCK7 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK7 --check-prefix CK7-64 -// RUN: %clang_cc1 -DCK7 -verify -fopenmp -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK7 --check-prefix CK7-32 -// RUN: %clang_cc1 -DCK7 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK7 --check-prefix CK7-32 +// RUN: %clang_cc1 -DCK7 -verify -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK7 --check-prefix CK7-64 +// RUN: %clang_cc1 -DCK7 -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK7 --check-prefix CK7-64 +// RUN: %clang_cc1 -DCK7 -verify -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK7 --check-prefix CK7-32 +// RUN: %clang_cc1 -DCK7 -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK7 --check-prefix CK7-32 #ifdef CK7 // For a 32-bit targets, the value doesn't fit the size of the pointer, @@ -360,12 +360,12 @@ void implicit_maps_double (int a){ #endif ///==========================================================================/// -// RUN: %clang_cc1 -DCK8 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK8 -// RUN: %clang_cc1 -DCK8 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK8 -// RUN: %clang_cc1 -DCK8 -verify -fopenmp -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK8 -// RUN: %clang_cc1 -DCK8 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK8 +// RUN: %clang_cc1 -DCK8 -verify -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK8 +// RUN: %clang_cc1 -DCK8 -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK8 +// RUN: %clang_cc1 -DCK8 -verify -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK8 +// RUN: %clang_cc1 -DCK8 -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK8 #ifdef CK8 // CK8-DAG: [[SIZES:@.+]] = {{.+}}constant [1 x i[[sz:64|32]]] [i{{64|32}} 4] @@ -404,12 +404,12 @@ void implicit_maps_float (int a){ #endif ///==========================================================================/// -// RUN: %clang_cc1 -DCK9 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK9 -// RUN: %clang_cc1 -DCK9 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK9 -// RUN: %clang_cc1 -DCK9 -verify -fopenmp -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK9 -// RUN: %clang_cc1 -DCK9 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK9 +// RUN: %clang_cc1 -DCK9 -verify -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK9 +// RUN: %clang_cc1 -DCK9 -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK9 +// RUN: %clang_cc1 -DCK9 -verify -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK9 +// RUN: %clang_cc1 -DCK9 -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK9 #ifdef CK9 // CK9-DAG: [[SIZES:@.+]] = {{.+}}constant [1 x i[[sz:64|32]]] [i{{64|32}} 16] @@ -445,12 +445,12 @@ void implicit_maps_array (int a){ // CK9: {{.+}} = getelementptr inbounds [2 x double], [2 x double]* [[REF]], i[[sz]] 0, i[[sz]] 0 #endif ///==========================================================================/// -// RUN: %clang_cc1 -DCK10 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK10 -// RUN: %clang_cc1 -DCK10 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK10 -// RUN: %clang_cc1 -DCK10 -verify -fopenmp -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK10 -// RUN: %clang_cc1 -DCK10 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK10 +// RUN: %clang_cc1 -DCK10 -verify -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK10 +// RUN: %clang_cc1 -DCK10 -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK10 +// RUN: %clang_cc1 -DCK10 -verify -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK10 +// RUN: %clang_cc1 -DCK10 -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK10 #ifdef CK10 // CK10-DAG: [[SIZES:@.+]] = {{.+}}constant [1 x i[[sz:64|32]]] [i{{64|32}} {{8|4}}] @@ -487,12 +487,12 @@ void implicit_maps_pointer (){ #endif ///==========================================================================/// -// RUN: %clang_cc1 -DCK11 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK11 -// RUN: %clang_cc1 -DCK11 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK11 -// RUN: %clang_cc1 -DCK11 -verify -fopenmp -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK11 -// RUN: %clang_cc1 -DCK11 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK11 +// RUN: %clang_cc1 -DCK11 -verify -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK11 +// RUN: %clang_cc1 -DCK11 -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK11 +// RUN: %clang_cc1 -DCK11 -verify -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK11 +// RUN: %clang_cc1 -DCK11 -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK11 #ifdef CK11 // CK11-DAG: [[SIZES:@.+]] = {{.+}}constant [1 x i[[sz:64|32]]] [i{{64|32}} 16] @@ -527,12 +527,12 @@ void implicit_maps_double_complex (int a){ // CK11: {{.+}} = getelementptr inbounds { double, double }, { double, double }* [[REF]], i32 0, i32 0 #endif ///==========================================================================/// -// RUN: %clang_cc1 -DCK12 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK12 --check-prefix CK12-64 -// RUN: %clang_cc1 -DCK12 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK12 --check-prefix CK12-64 -// RUN: %clang_cc1 -DCK12 -verify -fopenmp -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK12 --check-prefix CK12-32 -// RUN: %clang_cc1 -DCK12 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK12 --check-prefix CK12-32 +// RUN: %clang_cc1 -DCK12 -verify -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK12 --check-prefix CK12-64 +// RUN: %clang_cc1 -DCK12 -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK12 --check-prefix CK12-64 +// RUN: %clang_cc1 -DCK12 -verify -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK12 --check-prefix CK12-32 +// RUN: %clang_cc1 -DCK12 -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK12 --check-prefix CK12-32 #ifdef CK12 // For a 32-bit targets, the value doesn't fit the size of the pointer, @@ -588,12 +588,12 @@ void implicit_maps_float_complex (int a){ // CK12-32: {{.+}} = getelementptr inbounds { float, float }, { float, float }* [[REF]], i32 0, i32 0 #endif ///==========================================================================/// -// RUN: %clang_cc1 -DCK13 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK13 -// RUN: %clang_cc1 -DCK13 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK13 -// RUN: %clang_cc1 -DCK13 -verify -fopenmp -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK13 -// RUN: %clang_cc1 -DCK13 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK13 +// RUN: %clang_cc1 -DCK13 -verify -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK13 +// RUN: %clang_cc1 -DCK13 -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK13 +// RUN: %clang_cc1 -DCK13 -verify -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK13 +// RUN: %clang_cc1 -DCK13 -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK13 #ifdef CK13 // We don't have a constant map size for VLAs. @@ -658,12 +658,12 @@ void implicit_maps_variable_length_array (int a){ // CK13: {{.+}} = getelementptr inbounds double, double* [[REF]], i[[sz]] %{{.+}} #endif ///==========================================================================/// -// RUN: %clang_cc1 -DCK14 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK14 --check-prefix CK14-64 -// RUN: %clang_cc1 -DCK14 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK14 --check-prefix CK14-64 -// RUN: %clang_cc1 -DCK14 -verify -fopenmp -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK14 --check-prefix CK14-32 -// RUN: %clang_cc1 -DCK14 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK14 --check-prefix CK14-32 +// RUN: %clang_cc1 -DCK14 -verify -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK14 --check-prefix CK14-64 +// RUN: %clang_cc1 -DCK14 -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK14 --check-prefix CK14-64 +// RUN: %clang_cc1 -DCK14 -verify -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK14 --check-prefix CK14-32 +// RUN: %clang_cc1 -DCK14 -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK14 --check-prefix CK14-32 #ifdef CK14 // CK14-DAG: [[ST:%.+]] = type { i32, double } @@ -732,12 +732,12 @@ void implicit_maps_class (int a){ #endif ///==========================================================================/// -// RUN: %clang_cc1 -DCK15 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK15 --check-prefix CK15-64 -// RUN: %clang_cc1 -DCK15 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK15 --check-prefix CK15-64 -// RUN: %clang_cc1 -DCK15 -verify -fopenmp -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK15 --check-prefix CK15-32 -// RUN: %clang_cc1 -DCK15 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK15 --check-prefix CK15-32 +// RUN: %clang_cc1 -DCK15 -verify -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK15 --check-prefix CK15-64 +// RUN: %clang_cc1 -DCK15 -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK15 --check-prefix CK15-64 +// RUN: %clang_cc1 -DCK15 -verify -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK15 --check-prefix CK15-32 +// RUN: %clang_cc1 -DCK15 -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK15 --check-prefix CK15-32 #ifdef CK15 // CK15: [[ST:%.+]] = type { i32, double, i32* } @@ -860,12 +860,12 @@ void implicit_maps_templated_class (int a){ #endif ///==========================================================================/// -// RUN: %clang_cc1 -DCK16 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK16 --check-prefix CK16-64 -// RUN: %clang_cc1 -DCK16 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK16 --check-prefix CK16-64 -// RUN: %clang_cc1 -DCK16 -verify -fopenmp -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK16 --check-prefix CK16-32 -// RUN: %clang_cc1 -DCK16 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK16 --check-prefix CK16-32 +// RUN: %clang_cc1 -DCK16 -verify -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK16 --check-prefix CK16-64 +// RUN: %clang_cc1 -DCK16 -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK16 --check-prefix CK16-64 +// RUN: %clang_cc1 -DCK16 -verify -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK16 --check-prefix CK16-32 +// RUN: %clang_cc1 -DCK16 -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK16 --check-prefix CK16-32 #ifdef CK16 // CK16-DAG: [[SIZES:@.+]] = {{.+}}constant [1 x i[[sz:64|32]]] [i{{64|32}} 4] @@ -913,12 +913,12 @@ void implicit_maps_templated_function (int a){ #endif ///==========================================================================/// -// RUN: %clang_cc1 -DCK17 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK17 -// RUN: %clang_cc1 -DCK17 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK17 -// RUN: %clang_cc1 -DCK17 -verify -fopenmp -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK17 -// RUN: %clang_cc1 -DCK17 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK17 +// RUN: %clang_cc1 -DCK17 -verify -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK17 +// RUN: %clang_cc1 -DCK17 -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK17 +// RUN: %clang_cc1 -DCK17 -verify -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK17 +// RUN: %clang_cc1 -DCK17 -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK17 #ifdef CK17 // CK17-DAG: [[ST:%.+]] = type { i32, double } @@ -961,12 +961,12 @@ void implicit_maps_struct (int a){ // CK17: {{.+}} = getelementptr inbounds [[ST]], [[ST]]* [[REF]], i32 0, i32 0 #endif ///==========================================================================/// -// RUN: %clang_cc1 -DCK18 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK18 --check-prefix CK18-64 -// RUN: %clang_cc1 -DCK18 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK18 --check-prefix CK18-64 -// RUN: %clang_cc1 -DCK18 -verify -fopenmp -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK18 --check-prefix CK18-32 -// RUN: %clang_cc1 -DCK18 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK18 --check-prefix CK18-32 +// RUN: %clang_cc1 -DCK18 -verify -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK18 --check-prefix CK18-64 +// RUN: %clang_cc1 -DCK18 -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -omptargets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK18 --check-prefix CK18-64 +// RUN: %clang_cc1 -DCK18 -verify -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK18 --check-prefix CK18-32 +// RUN: %clang_cc1 -DCK18 -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -omptargets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK18 --check-prefix CK18-32 #ifdef CK18 // CK18-DAG: [[SIZES:@.+]] = {{.+}}constant [1 x i[[sz:64|32]]] [i{{64|32}} 4] diff --git a/test/OpenMP/target_messages.cpp b/test/OpenMP/target_messages.cpp index ebac51ae0d3..86a91838ce0 100644 --- a/test/OpenMP/target_messages.cpp +++ b/test/OpenMP/target_messages.cpp @@ -1,4 +1,6 @@ // RUN: %clang_cc1 -verify -fopenmp -std=c++11 -o - %s +// RUN: not %clang_cc1 -fopenmp -std=c++11 -omptargets=aaa-bbb-ccc-ddd -o - %s 2>&1 | FileCheck %s +// CHECK: error: OpenMP target is invalid: 'aaa-bbb-ccc-ddd' void foo() { } diff --git a/test/PCH/chain-default-argument-instantiation.cpp b/test/PCH/chain-default-argument-instantiation.cpp new file mode 100644 index 00000000000..0accd544a38 --- /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 00000000000..0990517c55b --- /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/Preprocessor/aarch64-target-features.c b/test/Preprocessor/aarch64-target-features.c index 2630e32fc45..dbc29cff292 100644 --- a/test/Preprocessor/aarch64-target-features.c +++ b/test/Preprocessor/aarch64-target-features.c @@ -92,11 +92,13 @@ // RUN: %clang -target aarch64 -mcpu=cortex-a53 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-A53 %s // RUN: %clang -target aarch64 -mcpu=cortex-a57 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-A57 %s // RUN: %clang -target aarch64 -mcpu=cortex-a72 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-A72 %s +// RUN: %clang -target aarch64 -mcpu=exynos-m1 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-M1 %s // CHECK-MCPU-CYCLONE: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+neon" "-target-feature" "+crc" "-target-feature" "+crypto" "-target-feature" "+zcm" "-target-feature" "+zcz" // CHECK-MCPU-A35: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+neon" "-target-feature" "+crc" "-target-feature" "+crypto" // CHECK-MCPU-A53: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+neon" "-target-feature" "+crc" "-target-feature" "+crypto" // CHECK-MCPU-A57: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+neon" "-target-feature" "+crc" "-target-feature" "+crypto" // CHECK-MCPU-A72: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+neon" "-target-feature" "+crc" "-target-feature" "+crypto" +// CHECK-MCPU-M1: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+neon" "-target-feature" "+crc" "-target-feature" "+crypto" // RUN: %clang -target x86_64-apple-macosx -arch arm64 -### -c %s 2>&1 | FileCheck --check-prefix=CHECK-ARCH-ARM64 %s // CHECK-ARCH-ARM64: "-target-cpu" "cyclone" "-target-feature" "+neon" "-target-feature" "+crc" "-target-feature" "+crypto" "-target-feature" "+zcm" "-target-feature" "+zcz" diff --git a/test/Profile/c-attributes.c b/test/Profile/c-attributes.c deleted file mode 100644 index 2dcc180624c..00000000000 --- a/test/Profile/c-attributes.c +++ /dev/null @@ -1,48 +0,0 @@ -// Test that instrumentation based profiling sets function attributes correctly. - -// RUN: llvm-profdata merge %S/Inputs/c-attributes.proftext -o %t.profdata -// RUN: %clang %s -o - -mllvm -disable-llvm-optzns -emit-llvm -S -fprofile-instr-use=%t.profdata | FileCheck %s - -extern int atoi(const char *); - -// CHECK: hot_100_percent(i32{{.*}}%i) [[HOT:#[0-9]+]] -void hot_100_percent(int i) { - while (i > 0) - i--; -} - -// CHECK: hot_40_percent(i32{{.*}}%i) [[HOT]] -void hot_40_percent(int i) { - while (i > 0) - i--; -} - -// CHECK: normal_func(i32{{.*}}%i) [[NORMAL:#[0-9]+]] -void normal_func(int i) { - while (i > 0) - i--; -} - -// CHECK: cold_func(i32{{.*}}%i) [[COLD:#[0-9]+]] -void cold_func(int i) { - while (i > 0) - i--; -} - -// CHECK: attributes [[HOT]] = { inlinehint nounwind {{.*}} } -// CHECK: attributes [[NORMAL]] = { nounwind {{.*}} } -// CHECK: attributes [[COLD]] = { cold nounwind {{.*}} } - -int main(int argc, const char *argv[]) { - int max = atoi(argv[1]); - int i; - for (i = 0; i < max; i++) - hot_100_percent(i); - for (i = 0; i < max * 4 / 10; i++) - hot_40_percent(i); - for (i = 0; i < max * 2 / 10; i++) - normal_func(i); - for (i = 0; i < max / 200; i++) - cold_func(i); - return 0; -} diff --git a/test/Profile/func-entry.c b/test/Profile/func-entry.c index 32c20a2a458..1ecae601a4d 100644 --- a/test/Profile/func-entry.c +++ b/test/Profile/func-entry.c @@ -5,10 +5,10 @@ void foo(void); -// CHECK: @foo() #0 !prof [[FOO:![0-9]+]] +// CHECK: @foo() #{{[0-9]}} !prof [[FOO:![0-9]+]] void foo() { return; } -// CHECK: @main() #1 !prof [[MAIN:![0-9]+]] +// CHECK: @main() #{{[0-9]}} !prof [[MAIN:![0-9]+]] int main() { int i; for (i = 0; i < 10000; i++) foo(); diff --git a/test/Sema/darwin-tls.c b/test/Sema/darwin-tls.c new file mode 100644 index 00000000000..0fcf096d92b --- /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/implicit-builtin-freestanding.c b/test/Sema/implicit-builtin-freestanding.c index 385cf1f751c..f77bccc48bb 100644 --- a/test/Sema/implicit-builtin-freestanding.c +++ b/test/Sema/implicit-builtin-freestanding.c @@ -1,4 +1,6 @@ // RUN: %clang_cc1 -fsyntax-only -verify -ffreestanding %s +// RUN: %clang_cc1 -fsyntax-only -verify -fno-builtin %s +// RUN: %clang_cc1 -fsyntax-only -verify -fno-builtin-malloc %s // expected-no-diagnostics int malloc(int a) { return a; } diff --git a/test/Sema/pass-object-size.c b/test/Sema/pass-object-size.c index e4f460b1785..6f375c0e94d 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/SemaCXX/anonymous-union.cpp b/test/SemaCXX/anonymous-union.cpp index 3520245a03a..0b654266f75 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 b8f0e076a2b..89751a493ee 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,66 @@ 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(); + } +} diff --git a/test/SemaCXX/pass-object-size.cpp b/test/SemaCXX/pass-object-size.cpp index bec0c1c55f2..94c9cc9c8aa 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/cond.cl b/test/SemaOpenCL/cond.cl index 8cc4f1e8e91..60f70564d86 100644 --- a/test/SemaOpenCL/cond.cl +++ b/test/SemaOpenCL/cond.cl @@ -128,5 +128,5 @@ int foo2(int); unsigned int ntest12(int2 C) { - return (unsigned int)(C ? foo1 : foo2); // expected-error {{taking address of function is not allowed}} + return (unsigned int)(C ? foo1 : foo2); // expected-error {{taking address of function is not allowed}} expected-error {{taking address of function is not allowed}} } diff --git a/test/SemaOpenCL/func_ptr.cl b/test/SemaOpenCL/func_ptr.cl index f21a3d3265a..abeab73a779 100644 --- a/test/SemaOpenCL/func_ptr.cl +++ b/test/SemaOpenCL/func_ptr.cl @@ -11,6 +11,9 @@ void bar() foo((void*)foo); // expected-error{{taking address of function is not allowed}} foo(&foo); // expected-error{{taking address of function is not allowed}} + // initializing an array with the address of functions is an error + void* vptrarr[2] = {foo, &foo}; // expected-error{{taking address of function is not allowed}} expected-error{{taking address of function is not allowed}} + // just calling a function is correct foo(0); } diff --git a/test/SemaTemplate/default-arguments-cxx0x.cpp b/test/SemaTemplate/default-arguments-cxx0x.cpp index 4cfd7a5843f..0c97c2056b7 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/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c index 48f22eb4bbf..2a6002537ec 100644 --- a/tools/c-index-test/c-index-test.c +++ b/tools/c-index-test/c-index-test.c @@ -1507,6 +1507,22 @@ static enum CXChildVisitResult PrintBitWidth(CXCursor cursor, CXCursor p, return CXChildVisit_Recurse; } +/******************************************************************************/ +/* Type declaration testing */ +/******************************************************************************/ + +static enum CXChildVisitResult PrintTypeDeclaration(CXCursor cursor, CXCursor p, + CXClientData d) { + CXCursor typeDeclaration = clang_getTypeDeclaration(clang_getCursorType(cursor)); + + if (clang_isDeclaration(typeDeclaration.kind)) { + PrintCursor(cursor, NULL); + PrintTypeAndTypeKind(clang_getCursorType(typeDeclaration), " [typedeclaration=%s] [typekind=%s]\n"); + } + + return CXChildVisit_Recurse; +} + /******************************************************************************/ /* Loading ASTs/source. */ /******************************************************************************/ @@ -1593,6 +1609,8 @@ int perform_test_load_source(int argc, const char **argv, int num_unsaved_files = 0; enum CXErrorCode Err; int result; + unsigned Repeats = 0; + unsigned I; Idx = clang_createIndex(/* excludeDeclsFromPCH */ (!strcmp(filter, "local") || @@ -1609,6 +1627,9 @@ int perform_test_load_source(int argc, const char **argv, return -1; } + if (getenv("CINDEXTEST_EDITING")) + Repeats = 5; + Err = clang_parseTranslationUnit2(Idx, 0, argv + num_unsaved_files, argc - num_unsaved_files, @@ -1622,6 +1643,22 @@ int perform_test_load_source(int argc, const char **argv, return 1; } + for (I = 0; I != Repeats; ++I) { + if (checkForErrors(TU) != 0) + return -1; + + if (Repeats > 1) { + Err = clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files, + clang_defaultReparseOptions(TU)); + if (Err != CXError_Success) { + describeLibclangFailure(Err); + free_remapped_files(unsaved_files, num_unsaved_files); + clang_disposeIndex(Idx); + return 1; + } + } + } + result = perform_test_load(Idx, TU, filter, NULL, Visitor, PV, CommentSchemaFile); free_remapped_files(unsaved_files, num_unsaved_files); @@ -4116,6 +4153,7 @@ static void print_usage(void) { " c-index-test -test-print-type {}*\n" " c-index-test -test-print-type-size {}*\n" " c-index-test -test-print-bitwidth {}*\n" + " c-index-test -test-print-type-declaration {}*\n" " c-index-test -print-usr [ {}]*\n" " c-index-test -print-usr-file \n" " c-index-test -write-pch \n"); @@ -4209,6 +4247,9 @@ int cindextest_main(int argc, const char **argv) { else if (argc > 2 && strcmp(argv[1], "-test-print-type-size") == 0) return perform_test_load_source(argc - 2, argv + 2, "all", PrintTypeSize, 0); + else if (argc > 2 && strcmp(argv[1], "-test-print-type-declaration") == 0) + return perform_test_load_source(argc - 2, argv + 2, "all", + PrintTypeDeclaration, 0); else if (argc > 2 && strcmp(argv[1], "-test-print-bitwidth") == 0) return perform_test_load_source(argc - 2, argv + 2, "all", PrintBitWidth, 0); diff --git a/tools/libclang/CIndexInclusionStack.cpp b/tools/libclang/CIndexInclusionStack.cpp index 365609b4f37..09593745335 100644 --- a/tools/libclang/CIndexInclusionStack.cpp +++ b/tools/libclang/CIndexInclusionStack.cpp @@ -21,56 +21,81 @@ #include "llvm/Support/raw_ostream.h" using namespace clang; -extern "C" { -void clang_getInclusions(CXTranslationUnit TU, CXInclusionVisitor CB, - CXClientData clientData) { - if (cxtu::isNotUsableTU(TU)) { - LOG_BAD_TU(TU); - return; - } - +static void getInclusions(const SrcMgr::SLocEntry &(SourceManager::*Getter)(unsigned, bool*) const, unsigned n, + CXTranslationUnit TU, CXInclusionVisitor CB, + CXClientData clientData) +{ ASTUnit *CXXUnit = cxtu::getASTUnit(TU); SourceManager &SM = CXXUnit->getSourceManager(); ASTContext &Ctx = CXXUnit->getASTContext(); - SmallVector InclusionStack; - unsigned n = SM.local_sloc_entry_size(); - - // In the case where all the SLocEntries are in an external source, traverse - // those SLocEntries as well. This is the case where we are looking - // at the inclusion stack of an AST/PCH file. - const SrcMgr::SLocEntry &(SourceManager::*Getter)(unsigned, bool*) const; - if (n == 1) { - Getter = &SourceManager::getLoadedSLocEntry; - n = SM.loaded_sloc_entry_size(); - } else - Getter = &SourceManager::getLocalSLocEntry; + const bool HasPreamble = SM.getPreambleFileID().isValid(); for (unsigned i = 0 ; i < n ; ++i) { bool Invalid = false; const SrcMgr::SLocEntry &SL = (SM.*Getter)(i, &Invalid); - + if (!SL.isFile() || Invalid) continue; const SrcMgr::FileInfo &FI = SL.getFile(); if (!FI.getContentCache()->OrigEntry) continue; - - // Build the inclusion stack. + + // If this is the main file, and there is a preamble, skip this SLoc. The + // inclusions of the preamble already showed it. SourceLocation L = FI.getIncludeLoc(); + if (HasPreamble && CXXUnit->isInMainFileID(L)) + continue; + + // Build the inclusion stack. InclusionStack.clear(); while (L.isValid()) { PresumedLoc PLoc = SM.getPresumedLoc(L); InclusionStack.push_back(cxloc::translateSourceLocation(Ctx, L)); L = PLoc.isValid()? PLoc.getIncludeLoc() : SourceLocation(); } - + + // If there is a preamble, the last entry is the "inclusion" of that + // preamble into the main file, which has the bogus entry of main.c:1:1 + if (HasPreamble && !InclusionStack.empty()) + InclusionStack.pop_back(); + // Callback to the client. // FIXME: We should have a function to construct CXFiles. CB(static_cast( - const_cast(FI.getContentCache()->OrigEntry)), + const_cast(FI.getContentCache()->OrigEntry)), InclusionStack.data(), InclusionStack.size(), clientData); - } + } +} + + +extern "C" { +void clang_getInclusions(CXTranslationUnit TU, CXInclusionVisitor CB, + CXClientData clientData) { + if (cxtu::isNotUsableTU(TU)) { + LOG_BAD_TU(TU); + return; + } + + SourceManager &SM = cxtu::getASTUnit(TU)->getSourceManager(); + const unsigned n = SM.local_sloc_entry_size(); + + // In the case where all the SLocEntries are in an external source, traverse + // those SLocEntries as well. This is the case where we are looking + // at the inclusion stack of an AST/PCH file. Also, if we are not looking at + // a AST/PCH file, but this file has a pre-compiled preamble, we also need + // to look in that file. + if (n == 1 || SM.getPreambleFileID().isValid()) { + getInclusions(&SourceManager::getLoadedSLocEntry, + SM.loaded_sloc_entry_size(), TU, CB, clientData); + } + + // Not a PCH/AST file. Note, if there is a preamble, it could still be that + // there are #includes in this file (e.g. for any include after the first + // declaration). + if (n != 1) + getInclusions(&SourceManager::getLocalSLocEntry, n, TU, CB, clientData); + } } // end extern C diff --git a/tools/libclang/CXType.cpp b/tools/libclang/CXType.cpp index 72c12cd16b9..44bb631f786 100644 --- a/tools/libclang/CXType.cpp +++ b/tools/libclang/CXType.cpp @@ -412,6 +412,12 @@ CXCursor clang_getTypeDeclaration(CXType CT) { .getAsTemplateDecl(); break; + case Type::Auto: + TP = cast(TP)->getDeducedType().getTypePtrOrNull(); + if (TP) + goto try_again; + break; + case Type::InjectedClassName: D = cast(TP)->getDecl(); break; diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp index 351ff31b17e..e9af8bf4a99 100644 --- a/unittests/Format/FormatTest.cpp +++ b/unittests/Format/FormatTest.cpp @@ -3607,6 +3607,7 @@ TEST_F(FormatTest, ConstructorInitializers) { FormatStyle OnePerLine = getLLVMStyle(); OnePerLine.ConstructorInitializerAllOnOneLineOrOnePerLine = true; + OnePerLine.AllowAllParametersOfDeclarationOnNextLine = false; verifyFormat("SomeClass::Constructor()\n" " : aaaaaaaaaaaaa(aaaaaaaaaaaaaa),\n" " aaaaaaaaaaaaa(aaaaaaaaaaaaaa),\n" @@ -3633,6 +3634,13 @@ TEST_F(FormatTest, ConstructorInitializers) { " : aaaaa(aaaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaaaa,\n" " aaaaaaaaaaaaaaaaaaaaaa) {}", OnePerLine); + OnePerLine.BinPackParameters = false; + verifyFormat( + "Constructor()\n" + " : aaaaaaaaaaaaaaaaaaaaaaaa(\n" + " aaaaaaaaaaa().aaa(),\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {}", + OnePerLine); OnePerLine.ColumnLimit = 60; verifyFormat("Constructor()\n" " : aaaaaaaaaaaaaaaaaaaa(a),\n" @@ -4157,17 +4165,14 @@ TEST_F(FormatTest, FormatsBuilderPattern) { verifyFormat("return aaaaaaaaaaaaaaaaa->aaaaa().aaaaaaaaaaaaa().aaaaaa() <\n" " aaaaaaaaaaaaaaa->aaaaa().aaaaaaaaaaaaa().aaaaaa();"); verifyFormat( - "aaaaaaa->aaaaaaa->aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n" - " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n" + "aaaaaaa->aaaaaaa\n" + " ->aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n" " ->aaaaaaaa(aaaaaaaaaaaaaaa);"); verifyFormat( "aaaaaaa->aaaaaaa\n" " ->aaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n" " ->aaaaaaaa(aaaaaaaaaaaaaaa);"); - verifyFormat( - "return aaaaaaaaaaaaaaaa\n" - " .aaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaa)\n" - " .aaaa(aaaaaaaaaaaaaa);"); verifyFormat( "aaaaaaaaaaaaaaaaaaa()->aaaaaa(bbbbb)->aaaaaaaaaaaaaaaaaaa( // break\n" " aaaaaaaaaaaaaa);"); @@ -4238,6 +4243,25 @@ TEST_F(FormatTest, FormatsBuilderPattern) { "return !soooooooooooooome_map\n" " .insert(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n" " .second;"); + verifyFormat( + "return aaaaaaaaaaaaaaaa\n" + " .aaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaa)\n" + " .aaaa(aaaaaaaaaaaaaa);"); + // No hanging indent here. + verifyFormat("aaaaaaaaaaaaaaaa.aaaaaaaaaaaaaa.aaaaaaaaaaaaaaa(\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);"); + verifyFormat("aaaaaaaaaaaaaaaa.aaaaaaaaaaaaaa().aaaaaaaaaaaaaaa(\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);"); + verifyFormat("aaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaa)\n" + " .aaa(aaaaaaaaaaaaaaaaaaaaaaaaaaaaa);", + getLLVMStyleWithColumns(60)); + verifyFormat("aaaaaaaaaaaaaaaaaa\n" + " .aaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaa)\n" + " .aaa(aaaaaaaaaaaaaaaaaaaaaaaaaaaaa);", + getLLVMStyleWithColumns(59)); + verifyFormat("aaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n" + " .aaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);"); } TEST_F(FormatTest, BreaksAccordingToOperatorPrecedence) { @@ -5052,6 +5076,15 @@ TEST_F(FormatTest, AlignsPipes) { verifyFormat("llvm::errs() << aaaaaaaaaaaaaaaaaaaaaa << endl\n" " << bbbbbbbbbbbbbbbbbbbbbb << endl;"); verifyFormat("llvm::errs() << endl << bbbbbbbbbbbbbbbbbbbbbb << endl;"); + + // Handle '\n'. + verifyFormat("llvm::errs() << aaaaaaaaaaaaaaaaaaaaaa << \"\\n\"\n" + " << bbbbbbbbbbbbbbbbbbbbbb << \"\\n\";"); + verifyFormat("llvm::errs() << aaaaaaaaaaaaaaaaaaaaaa << \'\\n\'\n" + " << bbbbbbbbbbbbbbbbbbbbbb << \'\\n\';"); + verifyFormat("llvm::errs() << aaaa << \"aaaaaaaaaaaaaaaaaa\\n\"\n" + " << bbbb << \"bbbbbbbbbbbbbbbbbb\\n\";"); + verifyFormat("llvm::errs() << \"\\n\" << bbbbbbbbbbbbbbbbbbbbbb << \"\\n\";"); } TEST_F(FormatTest, UnderstandsEquals) { @@ -7487,8 +7520,8 @@ TEST_F(FormatTest, FormatObjCMethodExpr) { " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa];"); verifyFormat("[aaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaa[aaaaaaaaaaaaaaaaaaaaa]\n" " aaaaaaaaaaaaaaaaaaaaaa];"); - verifyFormat("[call aaaaaaaa.aaaaaa.aaaaaaaa.aaaaaaaa.aaaaaaaa\n" - " .aaaaaaaa.aaaaaaaa];", // FIXME: Indentation seems off. + verifyFormat("[call aaaaaaaa.aaaaaa.aaaaaaaa.aaaaaaaa.aaaaaaaa.aaaaaaaa\n" + " .aaaaaaaa];", // FIXME: Indentation seems off. getLLVMStyleWithColumns(60)); verifyFormat( @@ -8283,7 +8316,7 @@ TEST_F(FormatTest, ConfigurableUseOfTab) { "\taaaaaaaaaaaaaaaaaaaaaaaaaaaa();\n" "};", Tab); - verifyFormat("enum A {\n" + verifyFormat("enum AA {\n" "\ta1, // Force multiple lines\n" "\ta2,\n" "\ta3\n" @@ -10605,6 +10638,7 @@ TEST_F(FormatTest, FormatsLambdas) { // Lambdas created through weird macros. verifyFormat("void f() {\n" " MACRO((const AA &a) { return 1; });\n" + " MACRO((AA &a) { return 1; });\n" "}"); verifyFormat("if (blah_blah(whatever, whatever, [] {\n" diff --git a/unittests/Format/FormatTestJS.cpp b/unittests/Format/FormatTestJS.cpp index 2f67bdf549c..2f1ba5bc146 100644 --- a/unittests/Format/FormatTestJS.cpp +++ b/unittests/Format/FormatTestJS.cpp @@ -288,6 +288,11 @@ TEST_F(FormatTestJS, ArrayLiterals) { " bbbbbbbbbbbbbbbbbbbbbbbbbbb,\n" " ccccccccccccccccccccccccccc\n" "];"); + verifyFormat("return [\n" + " aaaa().bbbbbbbb('A'),\n" + " aaaa().bbbbbbbb('B'),\n" + " aaaa().bbbbbbbb('C'),\n" + "];"); verifyFormat("var someVariable = SomeFunction([\n" " aaaaaaaaaaaaaaaaaaaaaaaaaaa,\n" " bbbbbbbbbbbbbbbbbbbbbbbbbbb,\n" @@ -812,6 +817,7 @@ TEST_F(FormatTestJS, MetadataAnnotations) { TEST_F(FormatTestJS, Modules) { verifyFormat("import SomeThing from 'some/module.js';"); verifyFormat("import {X, Y} from 'some/module.js';"); + verifyFormat("import a, {X, Y} from 'some/module.js';"); verifyFormat("import {\n" " VeryLongImportsAreAnnoying,\n" " VeryLongImportsAreAnnoying,\n"