diff --git a/CMakeLists.txt b/CMakeLists.txt index ca696b1ce79f..9e43a103b2bc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -579,10 +579,17 @@ if (CLANG_ENABLE_BOOTSTRAP) add_dependencies(clang-bootstrap-deps compiler-rt) endif() + set(C_COMPILER "clang") + set(CXX_COMPILER "clang++") + if(WIN32) + set(C_COMPILER "clang-cl.exe") + set(CXX_COMPILER "clang-cl.exe") + 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) + -DCMAKE_CXX_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/${CXX_COMPILER} + -DCMAKE_C_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/${C_COMPILER} + -DCMAKE_ASM_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/${C_COMPILER}) if(BOOTSTRAP_LLVM_BUILD_INSTRUMENTED) add_dependencies(clang-bootstrap-deps llvm-profdata) diff --git a/cmake/caches/Apple-stage2.cmake b/cmake/caches/Apple-stage2.cmake index 11c595c1530f..f07973dc0ab2 100644 --- a/cmake/caches/Apple-stage2.cmake +++ b/cmake/caches/Apple-stage2.cmake @@ -13,6 +13,7 @@ set(CLANG_LINKS_TO_CREATE clang++ cc c++ CACHE STRING "") set(CMAKE_MACOSX_RPATH ON CACHE BOOL "") set(LLVM_ENABLE_ZLIB ON CACHE BOOL "") set(LLVM_ENABLE_BACKTRACES OFF CACHE BOOL "") +set(LLVM_ENABLE_MODULES ON CACHE BOOL "") set(LLVM_EXTERNALIZE_DEBUGINFO ON CACHE BOOL "") set(CLANG_PLUGIN_SUPPORT OFF CACHE BOOL "") set(BUG_REPORT_URL "http://developer.apple.com/bugreporter/" CACHE STRING "") @@ -28,8 +29,10 @@ set(LLVM_BUILD_TESTS ON CACHE BOOL "") set(LLVM_ENABLE_LTO ON CACHE BOOL "") set(CMAKE_C_FLAGS "-fno-stack-protector -fno-common -Wno-profile-instr-unprofiled" CACHE STRING "") set(CMAKE_CXX_FLAGS "-fno-stack-protector -fno-common -Wno-profile-instr-unprofiled" CACHE STRING "") -set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 -gline-tables-only -DNDEBUG" CACHE STRING "") -set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -gline-tables-only -DNDEBUG" CACHE STRING "") +if(LLVM_ENABLE_LTO AND NOT LLVM_ENABLE_LTO STREQUAL "THIN") + set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 -gline-tables-only -DNDEBUG" CACHE STRING "") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -gline-tables-only -DNDEBUG" CACHE STRING "") +endif() set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "") set(LIBCXX_INSTALL_LIBRARY OFF CACHE BOOL "") diff --git a/cmake/caches/DistributionExample.cmake b/cmake/caches/DistributionExample.cmake index 862f547c1656..551f4ee07eac 100644 --- a/cmake/caches/DistributionExample.cmake +++ b/cmake/caches/DistributionExample.cmake @@ -29,6 +29,13 @@ set(CLANG_BOOTSTRAP_TARGETS # Setup the bootstrap build. set(CLANG_ENABLE_BOOTSTRAP ON CACHE BOOL "") -set(CLANG_BOOTSTRAP_CMAKE_ARGS - -C ${CMAKE_CURRENT_LIST_DIR}/DistributionExample-stage2.cmake - CACHE STRING "") + +if(STAGE2_CACHE_FILE) + set(CLANG_BOOTSTRAP_CMAKE_ARGS + -C ${STAGE2_CACHE_FILE} + CACHE STRING "") +else() + set(CLANG_BOOTSTRAP_CMAKE_ARGS + -C ${CMAKE_CURRENT_LIST_DIR}/DistributionExample-stage2.cmake + CACHE STRING "") +endif() diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt index 13b79fdfa534..d2956c18f80c 100644 --- a/docs/CMakeLists.txt +++ b/docs/CMakeLists.txt @@ -91,8 +91,8 @@ endif() endif() if (LLVM_ENABLE_SPHINX) + include(AddSphinxTarget) if (SPHINX_FOUND) - include(AddSphinxTarget) if (${SPHINX_OUTPUT_HTML}) add_sphinx_target(html clang) add_custom_command(TARGET docs-clang-html POST_BUILD diff --git a/docs/ClangFormatStyleOptions.rst b/docs/ClangFormatStyleOptions.rst index ed628e370087..f54acd9b81dd 100644 --- a/docs/ClangFormatStyleOptions.rst +++ b/docs/ClangFormatStyleOptions.rst @@ -209,23 +209,45 @@ the configuration (without a prefix: ``Auto``). float b = 23; std::string ccc = 23; -**AlignEscapedNewlinesLeft** (``bool``) - If ``true``, aligns escaped newlines as far left as possible. - Otherwise puts them into the right-most column. +**AlignEscapedNewlines** (``EscapedNewlineAlignmentStyle``) + Options for aligning backslashes in escaped newlines. - .. code-block:: c++ + Possible values: + + * ``ENAS_DontAlign`` (in configuration: ``DontAlign``) + Don't align escaped newlines. + + .. code-block:: c++ + + #define A \ + int aaaa; \ + int b; \ + int dddddddddd; + + * ``ENAS_Left`` (in configuration: ``Left``) + Align escaped newlines as far left as possible. + + .. code-block:: c++ + + true: + #define A \ + int aaaa; \ + int b; \ + int dddddddddd; + + false: + + * ``ENAS_Right`` (in configuration: ``Right``) + Align escaped newlines in the right-most column. + + .. code-block:: c++ + + #define A \ + int aaaa; \ + int b; \ + int dddddddddd; - true: - #define A \ - int aaaa; \ - int b; \ - int dddddddddd; - false: - #define A \ - int aaaa; \ - int b; \ - int dddddddddd; **AlignOperands** (``bool``) If ``true``, horizontally align operands of binary and ternary @@ -1525,7 +1547,7 @@ the configuration (without a prefix: ``Auto``). Use C++03-compatible syntax. * ``LS_Cpp11`` (in configuration: ``Cpp11``) - Use features of C++11, C++14 and C++1z (e.g. ``A>`` instead of + Use features of C++11, C++14 and C++1z (e.g. ``A>`` instead of ``A >``). * ``LS_Auto`` (in configuration: ``Auto``) diff --git a/docs/ThreadSafetyAnalysis.rst b/docs/ThreadSafetyAnalysis.rst index 47cf4ef3994e..ea8e98a1884b 100644 --- a/docs/ThreadSafetyAnalysis.rst +++ b/docs/ThreadSafetyAnalysis.rst @@ -884,11 +884,11 @@ implementation. // Deprecated. #define PT_GUARDED_VAR \ - THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded) + THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_var) // Deprecated. #define GUARDED_VAR \ - THREAD_ANNOTATION_ATTRIBUTE__(guarded) + THREAD_ANNOTATION_ATTRIBUTE__(guarded_var) // Replaced by REQUIRES #define EXCLUSIVE_LOCKS_REQUIRED(...) \ diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index c50ac1b6d248..462d9269f7ad 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -32,7 +32,7 @@ * compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable. */ #define CINDEX_VERSION_MAJOR 0 -#define CINDEX_VERSION_MINOR 38 +#define CINDEX_VERSION_MINOR 39 #define CINDEX_VERSION_ENCODE(major, minor) ( \ ((major) * 10000) \ @@ -4080,6 +4080,23 @@ CINDEX_LINKAGE unsigned clang_Cursor_isObjCOptional(CXCursor C); */ CINDEX_LINKAGE unsigned clang_Cursor_isVariadic(CXCursor C); +/** + * \brief Returns non-zero if the given cursor points to a symbol marked with + * external_source_symbol attribute. + * + * \param language If non-NULL, and the attribute is present, will be set to + * the 'language' string from the attribute. + * + * \param definedIn If non-NULL, and the attribute is present, will be set to + * the 'definedIn' string from the attribute. + * + * \param isGenerated If non-NULL, and the attribute is present, will be set to + * non-zero if the 'generated_declaration' is set in the attribute. + */ +CINDEX_LINKAGE unsigned clang_Cursor_isExternalSymbol(CXCursor C, + CXString *language, CXString *definedIn, + unsigned *isGenerated); + /** * \brief Given a cursor that represents a declaration, return the associated * comment's source range. The range may include multiple consecutive comments diff --git a/include/clang/AST/CXXInheritance.h b/include/clang/AST/CXXInheritance.h index 3cf058f26bc6..a7961ebe8ce6 100644 --- a/include/clang/AST/CXXInheritance.h +++ b/include/clang/AST/CXXInheritance.h @@ -161,7 +161,8 @@ class CXXBasePaths { void ComputeDeclsFound(); bool lookupInBases(ASTContext &Context, const CXXRecordDecl *Record, - CXXRecordDecl::BaseMatchesCallback BaseMatches); + CXXRecordDecl::BaseMatchesCallback BaseMatches, + bool LookupInDependent = false); public: typedef std::list::iterator paths_iterator; diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 573ea55de1fd..facef8e55f7a 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -966,9 +966,16 @@ class VarDecl : public DeclaratorDecl, public Redeclarable { /// hasLocalStorage - Returns true if a variable with function scope /// is a non-static local variable. bool hasLocalStorage() const { - if (getStorageClass() == SC_None) + if (getStorageClass() == SC_None) { + // OpenCL v1.2 s6.5.3: The __constant or constant address space name is + // used to describe variables allocated in global memory and which are + // accessed inside a kernel(s) as read-only variables. As such, variables + // in constant address space cannot have local storage. + if (getType().getAddressSpace() == LangAS::opencl_constant) + return false; // Second check is for C++11 [dcl.stc]p4. return !isFileVarDecl() && getTSCSpec() == TSCS_unspecified; + } // Global Named Register (GNU extension) if (getStorageClass() == SC_Register && !isLocalVarDeclOrParm()) @@ -2478,7 +2485,7 @@ class FieldDecl : public DeclaratorDecl, public Mergeable { void setCapturedVLAType(const VariableArrayType *VLAType); /// getParent - Returns the parent of this field declaration, which - /// is the struct in which this method is defined. + /// is the struct in which this field is defined. const RecordDecl *getParent() const { return cast(getDeclContext()); } diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 13921a132cfb..6965e8143ff6 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -1563,10 +1563,13 @@ class CXXRecordDecl : public RecordDecl { /// \param Paths used to record the paths from this class to its base class /// subobjects that match the search criteria. /// + /// \param LookupInDependent can be set to true to extend the search to + /// dependent base classes. + /// /// \returns true if there exists any path from this class to a base class /// subobject that matches the search criteria. - bool lookupInBases(BaseMatchesCallback BaseMatches, - CXXBasePaths &Paths) const; + bool lookupInBases(BaseMatchesCallback BaseMatches, CXXBasePaths &Paths, + bool LookupInDependent = false) const; /// \brief Base-class lookup callback that determines whether the given /// base class specifier refers to a specific class declaration. @@ -1607,6 +1610,16 @@ class CXXRecordDecl : public RecordDecl { static bool FindOrdinaryMember(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, DeclarationName Name); + /// \brief Base-class lookup callback that determines whether there exists + /// a member with the given name. + /// + /// This callback can be used with \c lookupInBases() to find members + /// of the given name within a C++ class hierarchy, including dependent + /// classes. + static bool + FindOrdinaryMemberInDependentClasses(const CXXBaseSpecifier *Specifier, + CXXBasePath &Path, DeclarationName Name); + /// \brief Base-class lookup callback that determines whether there exists /// an OpenMP declare reduction member with the given name. /// @@ -1633,6 +1646,14 @@ class CXXRecordDecl : public RecordDecl { /// \brief Get the indirect primary bases for this class. void getIndirectPrimaryBases(CXXIndirectPrimaryBaseSet& Bases) const; + /// Performs an imprecise lookup of a dependent name in this class. + /// + /// This function does not follow strict semantic rules and should be used + /// only when lookup rules can be relaxed, e.g. indexing. + std::vector + lookupDependentName(const DeclarationName &Name, + llvm::function_ref Filter); + /// Renders and displays an inheritance diagram /// for this C++ class and all of its base classes (transitively) using /// GraphViz. diff --git a/include/clang/AST/ExternalASTMerger.h b/include/clang/AST/ExternalASTMerger.h index 51d0c30ad23b..55459df1fe6b 100644 --- a/include/clang/AST/ExternalASTMerger.h +++ b/include/clang/AST/ExternalASTMerger.h @@ -44,6 +44,8 @@ class ExternalASTMerger : public ExternalASTSource { FindExternalLexicalDecls(const DeclContext *DC, llvm::function_ref IsKindWeWant, SmallVectorImpl &Result) override; + + void CompleteType(TagDecl *Tag) override; }; } // end namespace clang diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index 1b5850a05b37..cd2a39449825 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -2326,7 +2326,7 @@ DEF_TRAVERSE_STMT(LambdaExpr, { } TypeLoc TL = S->getCallOperator()->getTypeSourceInfo()->getTypeLoc(); - FunctionProtoTypeLoc Proto = TL.castAs(); + FunctionProtoTypeLoc Proto = TL.getAsAdjusted(); if (S->hasExplicitParameters() && S->hasExplicitResultType()) { // Visit the whole type. diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index 3eeeb1bdc971..4eb958e3f4d5 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -652,6 +652,30 @@ def Availability : InheritableAttr { .Case("tvos_app_extension", "tvOS (App Extension)") .Case("watchos_app_extension", "watchOS (App Extension)") .Default(llvm::StringRef()); +} +static llvm::StringRef getPlatformNameSourceSpelling(llvm::StringRef Platform) { + return llvm::StringSwitch(Platform) + .Case("ios", "iOS") + .Case("macos", "macOS") + .Case("tvos", "tvOS") + .Case("watchos", "watchOS") + .Case("ios_app_extension", "iOSApplicationExtension") + .Case("macos_app_extension", "macOSApplicationExtension") + .Case("tvos_app_extension", "tvOSApplicationExtension") + .Case("watchos_app_extension", "watchOSApplicationExtension") + .Default(Platform); +} +static llvm::StringRef canonicalizePlatformName(llvm::StringRef Platform) { + return llvm::StringSwitch(Platform) + .Case("iOS", "ios") + .Case("macOS", "macos") + .Case("tvOS", "tvos") + .Case("watchOS", "watchos") + .Case("iOSApplicationExtension", "ios_app_extension") + .Case("macOSApplicationExtension", "macos_app_extension") + .Case("tvOSApplicationExtension", "tvos_app_extension") + .Case("watchOSApplicationExtension", "watchos_app_extension") + .Default(Platform); } }]; let HasCustomParsing = 1; let DuplicatesAllowedWhileMerging = 1; diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def index 816ea156f979..a9ec172422ab 100644 --- a/include/clang/Basic/Builtins.def +++ b/include/clang/Basic/Builtins.def @@ -1409,6 +1409,9 @@ LANGBUILTIN(to_private, "v*v*", "tn", OCLC20_LANG) BUILTIN(__builtin_os_log_format_buffer_size, "zcC*.", "p:0:nut") BUILTIN(__builtin_os_log_format, "v*v*cC*.", "p:0:nt") +// Builtins for XRay +BUILTIN(__xray_customevent, "vcC*z", "") + #undef BUILTIN #undef LIBBUILTIN #undef LANGBUILTIN diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 05e03fab40fa..e1a41584023c 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -486,6 +486,7 @@ def UnneededInternalDecl : DiagGroup<"unneeded-internal-declaration">; def UnneededMemberFunction : DiagGroup<"unneeded-member-function">; def UnusedPrivateField : DiagGroup<"unused-private-field">; def UnusedFunction : DiagGroup<"unused-function", [UnneededInternalDecl]>; +def UnusedTemplate : DiagGroup<"unused-template", [UnneededInternalDecl]>; def UnusedMemberFunction : DiagGroup<"unused-member-function", [UnneededMemberFunction]>; def UnusedLabel : DiagGroup<"unused-label">; @@ -627,6 +628,7 @@ def Conversion : DiagGroup<"conversion", def Unused : DiagGroup<"unused", [UnusedArgument, UnusedFunction, UnusedLabel, // UnusedParameter, (matches GCC's behavior) + // UnusedTemplate, (clean-up libc++ before enabling) // UnusedMemberFunction, (clean-up llvm before enabling) UnusedPrivateField, UnusedLambdaCapture, UnusedLocalTypedef, UnusedValue, UnusedVariable, diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index a0c0e5f86449..1db6704f6d1f 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -303,6 +303,8 @@ def note_empty_parens_zero_initialize : Note< "replace parentheses with an initializer to declare a variable">; def warn_unused_function : Warning<"unused function %0">, InGroup, DefaultIgnore; +def warn_unused_template : Warning<"unused %select{function|variable}0 template %1">, + InGroup, DefaultIgnore; def warn_unused_member_function : Warning<"unused member function %0">, InGroup, DefaultIgnore; def warn_used_but_marked_unused: Warning<"%0 was marked unused but was used">, @@ -2463,6 +2465,9 @@ def err_attribute_invalid_size : Error< "vector size not an integral multiple of component size">; def err_attribute_zero_size : Error<"zero vector size">; def err_attribute_size_too_large : Error<"vector size too large">; +def err_typecheck_vector_not_convertable_implict_truncation : Error< + "cannot convert between %select{scalar|vector}0 type %1 and vector type" + " %2 as implicit conversion would cause truncation">; def err_typecheck_vector_not_convertable : Error< "cannot convert between vector values of different size (%0 and %1)">; def err_typecheck_vector_not_convertable_non_scalar : Error< @@ -4607,6 +4612,8 @@ def err_abi_tag_on_redeclaration : Error< "cannot add 'abi_tag' attribute in a redeclaration">; def err_new_abi_tag_on_redeclaration : Error< "'abi_tag' %0 missing in original declaration">; +def note_use_ifdef_guards : Note< + "unguarded header; consider using #ifdef guards or #pragma once">; def note_deleted_dtor_no_operator_delete : Note< "virtual destructor requires an unambiguous, accessible 'operator delete'">; @@ -5775,6 +5782,9 @@ def err_objc_object_assignment : Error< "cannot assign to class object (%0 invalid)">; def err_typecheck_invalid_operands : Error< "invalid operands to binary expression (%0 and %1)">; +def err_typecheck_logical_vector_expr_gnu_cpp_restrict : Error< + "logical expression with vector %select{type %1 and non-vector type %2|types" + " %1 and %2}0 is only supported in C++">; def err_typecheck_sub_ptr_compatible : Error< "%diff{$ and $ are not pointers to compatible types|" "pointers to incompatible types}0,1">; @@ -8186,9 +8196,20 @@ def err_undeclared_use_suggest : Error< "use of undeclared %0; did you mean %1?">; def err_undeclared_var_use_suggest : Error< "use of undeclared identifier %0; did you mean %1?">; +def err_no_template : Error<"no template named %0">; def err_no_template_suggest : Error<"no template named %0; did you mean %1?">; +def err_no_member_template : Error<"no template named %0 in %1">; def err_no_member_template_suggest : Error< "no template named %0 in %1; did you mean %select{|simply }2%3?">; +def err_non_template_in_template_id : Error< + "%0 does not name a template but is followed by template arguments">; +def err_non_template_in_template_id_suggest : Error< + "%0 does not name a template but is followed by template arguments; " + "did you mean %1?">; +def err_non_template_in_member_template_id_suggest : Error< + "member %0 of %1 is not a template; did you mean %select{|simply }2%3?">; +def note_non_template_in_template_id_found : Note< + "non-template declaration found by name lookup">; def err_mem_init_not_member_or_class_suggest : Error< "initializer %0 does not name a non-static data member or base " "class; did you mean the %select{base class|member}1 %2?">; @@ -8875,6 +8896,13 @@ def ext_equivalent_internal_linkage_decl_in_modules : ExtWarn< InGroup>; def note_equivalent_internal_linkage_decl : Note< "declared here%select{ in module '%1'|}0">; + +def note_redefinition_modules_same_file : Note< + "'%0' included multiple times, additional include site in header from module '%1'">; +def note_redefinition_modules_same_file_modulemap : Note< + "consider adding '%0' as part of '%1' definition">; +def note_redefinition_include_same_file : Note< + "'%0' included multiple times, additional include site here">; } let CategoryName = "Coroutines Issue" in { diff --git a/include/clang/Basic/TargetOptions.h b/include/clang/Basic/TargetOptions.h index 2889cce5963b..6ca1ba39c8fb 100644 --- a/include/clang/Basic/TargetOptions.h +++ b/include/clang/Basic/TargetOptions.h @@ -24,8 +24,7 @@ namespace clang { /// \brief Options for controlling the target. class TargetOptions { public: - /// If given, the name of the target triple to compile for. If not given the - /// target will be selected to match the host. + /// The name of the target triple to compile for. std::string Triple; /// When compiling for the device side, contains the triple used to compile diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 31015228f362..d812bd8ec032 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -827,6 +827,9 @@ def fno_sanitize_address_use_after_scope : Flag<["-"], "fno-sanitize-address-use Group, Flags<[CoreOption, DriverOption]>, HelpText<"Disable use-after-scope detection in AddressSanitizer">; +def fsanitize_address_globals_dead_stripping : Flag<["-"], "fsanitize-address-globals-dead-stripping">, + Group, + HelpText<"Enable linker dead stripping of globals in AddressSanitizer">; def fsanitize_recover : Flag<["-"], "fsanitize-recover">, Group; def fno_sanitize_recover : Flag<["-"], "fno-sanitize-recover">, Flags<[CoreOption, DriverOption]>, diff --git a/include/clang/Driver/SanitizerArgs.h b/include/clang/Driver/SanitizerArgs.h index c7b3e8006dd5..a9645d463fa1 100644 --- a/include/clang/Driver/SanitizerArgs.h +++ b/include/clang/Driver/SanitizerArgs.h @@ -35,6 +35,7 @@ class SanitizerArgs { int AsanFieldPadding = 0; bool AsanSharedRuntime = false; bool AsanUseAfterScope = true; + bool AsanGlobalsDeadStripping = false; bool LinkCXXRuntimes = false; bool NeedPIE = false; bool Stats = false; diff --git a/include/clang/Format/Format.h b/include/clang/Format/Format.h index 9bed253baca2..a963c6369aa9 100644 --- a/include/clang/Format/Format.h +++ b/include/clang/Format/Format.h @@ -98,22 +98,39 @@ struct FormatStyle { /// \endcode bool AlignConsecutiveDeclarations; - /// \brief If ``true``, aligns escaped newlines as far left as possible. - /// Otherwise puts them into the right-most column. - /// \code - /// true: - /// #define A \ - /// int aaaa; \ - /// int b; \ - /// int dddddddddd; - /// - /// false: - /// #define A \ - /// int aaaa; \ - /// int b; \ - /// int dddddddddd; - /// \endcode - bool AlignEscapedNewlinesLeft; + /// \brief Different styles for aligning escaped newlines. + enum EscapedNewlineAlignmentStyle { + /// \brief Don't align escaped newlines. + /// \code + /// #define A \ + /// int aaaa; \ + /// int b; \ + /// int dddddddddd; + /// \endcode + ENAS_DontAlign, + /// \brief Align escaped newlines as far left as possible. + /// \code + /// true: + /// #define A \ + /// int aaaa; \ + /// int b; \ + /// int dddddddddd; + /// + /// false: + /// \endcode + ENAS_Left, + /// \brief Align escaped newlines in the right-most column. + /// \code + /// #define A \ + /// int aaaa; \ + /// int b; \ + /// int dddddddddd; + /// \endcode + ENAS_Right, + }; + + /// \brief Options for aligning backslashes in escaped newlines. + EscapedNewlineAlignmentStyle AlignEscapedNewlines; /// \brief If ``true``, horizontally align operands of binary and ternary /// expressions. @@ -1347,7 +1364,7 @@ struct FormatStyle { AlignAfterOpenBracket == R.AlignAfterOpenBracket && AlignConsecutiveAssignments == R.AlignConsecutiveAssignments && AlignConsecutiveDeclarations == R.AlignConsecutiveDeclarations && - AlignEscapedNewlinesLeft == R.AlignEscapedNewlinesLeft && + AlignEscapedNewlines == R.AlignEscapedNewlines && AlignOperands == R.AlignOperands && AlignTrailingComments == R.AlignTrailingComments && AllowAllParametersOfDeclarationOnNextLine == diff --git a/include/clang/Frontend/CodeGenOptions.def b/include/clang/Frontend/CodeGenOptions.def index 7495ad808c99..251441d38ff8 100644 --- a/include/clang/Frontend/CodeGenOptions.def +++ b/include/clang/Frontend/CodeGenOptions.def @@ -137,6 +137,8 @@ CODEGENOPT(StructPathTBAA , 1, 0) ///< Whether or not to use struct-path TBAA CODEGENOPT(SaveTempLabels , 1, 0) ///< Save temporary labels. CODEGENOPT(SanitizeAddressUseAfterScope , 1, 0) ///< Enable use-after-scope detection ///< in AddressSanitizer +CODEGENOPT(SanitizeAddressGlobalsDeadStripping, 1, 0) ///< Enable linker dead stripping + ///< of globals in AddressSanitizer CODEGENOPT(SanitizeMemoryTrackOrigins, 2, 0) ///< Enable tracking origins in ///< MemorySanitizer CODEGENOPT(SanitizeMemoryUseAfterDtor, 1, 0) ///< Enable use-after-delete detection diff --git a/include/clang/Lex/MacroInfo.h b/include/clang/Lex/MacroInfo.h index 44b7b2e4a474..7da1e7b41ab8 100644 --- a/include/clang/Lex/MacroInfo.h +++ b/include/clang/Lex/MacroInfo.h @@ -105,9 +105,6 @@ class MacroInfo { /// \brief Must warn if the macro is unused at the end of translation unit. bool IsWarnIfUnused : 1; - /// \brief Whether this macro info was loaded from an AST file. - bool FromASTFile : 1; - /// \brief Whether this macro was used as header guard. bool UsedForHeaderGuard : 1; @@ -264,34 +261,16 @@ class MacroInfo { IsDisabled = true; } - /// \brief Determine whether this macro info came from an AST file (such as - /// a precompiled header or module) rather than having been parsed. - bool isFromASTFile() const { return FromASTFile; } - /// \brief Determine whether this macro was used for a header guard. bool isUsedForHeaderGuard() const { return UsedForHeaderGuard; } void setUsedForHeaderGuard(bool Val) { UsedForHeaderGuard = Val; } - /// \brief Retrieve the global ID of the module that owns this particular - /// macro info. - unsigned getOwningModuleID() const { - if (isFromASTFile()) - return *(const unsigned *)(this + 1); - - return 0; - } - void dump() const; private: unsigned getDefinitionLengthSlow(const SourceManager &SM) const; - void setOwningModuleID(unsigned ID) { - assert(isFromASTFile()); - *(unsigned *)(this + 1) = ID; - } - friend class Preprocessor; }; diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index 0e3f563785d4..114bf70ad59a 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -644,14 +644,6 @@ class Preprocessor { /// of that list. MacroInfoChain *MIChainHead; - struct DeserializedMacroInfoChain { - MacroInfo MI; - unsigned OwningModuleID; // MUST be immediately after the MacroInfo object - // so it can be accessed by MacroInfo::getOwningModuleID(). - DeserializedMacroInfoChain *Next; - }; - DeserializedMacroInfoChain *DeserialMIChainHead; - void updateOutOfDateIdentifier(IdentifierInfo &II) const; public: @@ -1669,10 +1661,6 @@ class Preprocessor { /// \brief Allocate a new MacroInfo object with the provided SourceLocation. MacroInfo *AllocateMacroInfo(SourceLocation L); - /// \brief Allocate a new MacroInfo object loaded from an AST file. - MacroInfo *AllocateDeserializedMacroInfo(SourceLocation L, - unsigned SubModuleID); - /// \brief Turn the specified lexer token into a fully checked and spelled /// filename, e.g. as an operand of \#include. /// @@ -1764,9 +1752,6 @@ class Preprocessor { /// macro name. void updateModuleMacroInfo(const IdentifierInfo *II, ModuleMacroInfo &Info); - /// \brief Allocate a new MacroInfo object. - MacroInfo *AllocateMacroInfo(); - DefMacroDirective *AllocateDefMacroDirective(MacroInfo *MI, SourceLocation Loc); UndefMacroDirective *AllocateUndefMacroDirective(SourceLocation UndefLoc); diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 8d0935dec1b6..f5a7e02941a7 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -1488,6 +1488,8 @@ class Parser : public CodeCompletionHandler { K == tok::plusplus || K == tok::minusminus); } + bool diagnoseUnknownTemplateId(ExprResult TemplateName, SourceLocation Less); + ExprResult ParsePostfixExpressionSuffix(ExprResult LHS); ExprResult ParseUnaryExprOrTypeTraitExpression(); ExprResult ParseBuiltinPrimaryExpression(); @@ -2723,10 +2725,7 @@ class Parser : public CodeCompletionHandler { bool ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc, bool ConsumeLastToken, bool ObjCGenericList); - bool ParseTemplateIdAfterTemplateName(TemplateTy Template, - SourceLocation TemplateNameLoc, - const CXXScopeSpec &SS, - bool ConsumeLastToken, + bool ParseTemplateIdAfterTemplateName(bool ConsumeLastToken, SourceLocation &LAngleLoc, TemplateArgList &TemplateArgs, SourceLocation &RAngleLoc); diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index e5961079f7c2..e910be14f969 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -1074,6 +1074,10 @@ class Sema { /// correctly named definition after the renamed definition. llvm::SmallPtrSet TypoCorrectedFunctionDefinitions; + /// Stack of types that correspond to the parameter entities that are + /// currently being copy-initialized. Can be empty. + llvm::SmallVector CurrentParameterCopyTypes; + void ReadMethodPool(Selector Sel); void updateOutOfDateSelector(Selector Sel); @@ -1456,6 +1460,11 @@ class Sema { /// The modules we're currently parsing. llvm::SmallVector ModuleScopes; + /// Get the module whose scope we are currently within. + Module *getCurrentModule() const { + return ModuleScopes.empty() ? nullptr : ModuleScopes.back().Module; + } + VisibleModuleSet VisibleModules; Module *CachedFakeTopLevelModule; @@ -1466,7 +1475,7 @@ class Sema { /// \brief Make a merged definition of an existing hidden definition \p ND /// visible at the specified location. - void makeMergedDefinitionVisible(NamedDecl *ND, SourceLocation Loc); + void makeMergedDefinitionVisible(NamedDecl *ND); bool isModuleVisible(Module *M) { return VisibleModules.isVisible(M); } @@ -1593,7 +1602,7 @@ class Sema { Scope *S, CXXScopeSpec *SS, ParsedType &SuggestedType, - bool AllowClassTemplates = false); + bool IsTemplateName = false); /// Attempt to behave like MSVC in situations where lookup of an unqualified /// type name has failed in a dependent context. In these situations, we @@ -1738,6 +1747,23 @@ class Sema { TemplateNameKindForDiagnostics getTemplateNameKindForDiagnostics(TemplateName Name); + /// Determine whether it's plausible that E was intended to be a + /// template-name. + bool mightBeIntendedToBeTemplateName(ExprResult E) { + if (!getLangOpts().CPlusPlus || E.isInvalid()) + return false; + if (auto *DRE = dyn_cast(E.get())) + return !DRE->hasExplicitTemplateArgs(); + if (auto *ME = dyn_cast(E.get())) + return !ME->hasExplicitTemplateArgs(); + // Any additional cases recognized here should also be handled by + // diagnoseExprIntendedAsTemplateName. + return false; + } + void diagnoseExprIntendedAsTemplateName(Scope *S, ExprResult TemplateName, + SourceLocation Less, + SourceLocation Greater); + Decl *ActOnDeclarator(Scope *S, Declarator &D); NamedDecl *HandleDeclarator(Scope *S, Declarator &D, @@ -2336,6 +2362,7 @@ class Sema { void MergeVarDeclTypes(VarDecl *New, VarDecl *Old, bool MergeTypeWithOld); void MergeVarDeclExceptionSpecs(VarDecl *New, VarDecl *Old); bool checkVarDeclRedefinition(VarDecl *OldDefn, VarDecl *NewDefn); + void notePreviousDefinition(SourceLocation Old, SourceLocation New); bool MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, Scope *S); // AssignmentAction - This is used by all the assignment diagnostic functions @@ -2726,7 +2753,8 @@ class Sema { resolveAddressOfOnlyViableOverloadCandidate(Expr *E, DeclAccessPair &FoundResult); - bool resolveAndFixAddressOfOnlyViableOverloadCandidate(ExprResult &SrcExpr); + bool resolveAndFixAddressOfOnlyViableOverloadCandidate( + ExprResult &SrcExpr, bool DoFunctionPointerConversion = false); FunctionDecl * ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl, @@ -3049,7 +3077,8 @@ class Sema { bool IncludeGlobalScope = true); void LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind, VisibleDeclConsumer &Consumer, - bool IncludeGlobalScope = true); + bool IncludeGlobalScope = true, + bool IncludeDependentBases = false); enum CorrectTypoKind { CTK_NonError, // CorrectTypo used in a non error recovery situation. @@ -6084,6 +6113,7 @@ class Sema { TemplateArgumentListInfo *ExplicitTemplateArgs, LookupResult &Previous); bool CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous); + void CompleteMemberSpecialization(NamedDecl *Member, LookupResult &Previous); DeclResult ActOnExplicitInstantiation(Scope *S, @@ -9259,6 +9289,8 @@ class Sema { /// type checking binary operators (subroutines of CreateBuiltinBinOp). QualType InvalidOperands(SourceLocation Loc, ExprResult &LHS, ExprResult &RHS); + QualType InvalidLogicalVectorOperands(SourceLocation Loc, ExprResult &LHS, + ExprResult &RHS); QualType CheckPointerToMemberOperands( // C++ 5.5 ExprResult &LHS, ExprResult &RHS, ExprValueKind &VK, SourceLocation OpLoc, bool isIndirect); @@ -10008,6 +10040,7 @@ class Sema { MacroInfo *MacroInfo, unsigned Argument); void CodeCompleteNaturalLanguage(); + void CodeCompleteAvailabilityPlatformName(); void GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo, SmallVectorImpl &Results); diff --git a/include/clang/Tooling/RefactoringCallbacks.h b/include/clang/Tooling/RefactoringCallbacks.h index 6ef9ea11f0ae..9862951149a3 100644 --- a/include/clang/Tooling/RefactoringCallbacks.h +++ b/include/clang/Tooling/RefactoringCallbacks.h @@ -47,6 +47,33 @@ class RefactoringCallback : public ast_matchers::MatchFinder::MatchCallback { Replacements Replace; }; +/// \brief Adaptor between \c ast_matchers::MatchFinder and \c +/// tooling::RefactoringTool. +/// +/// Runs AST matchers and stores the \c tooling::Replacements in a map. +class ASTMatchRefactorer { +public: + explicit ASTMatchRefactorer( + std::map &FileToReplaces); + + template + void addMatcher(const T &Matcher, RefactoringCallback *Callback) { + MatchFinder.addMatcher(Matcher, Callback); + Callbacks.push_back(Callback); + } + + void addDynamicMatcher(const ast_matchers::internal::DynTypedMatcher &Matcher, + RefactoringCallback *Callback); + + std::unique_ptr newASTConsumer(); + +private: + friend class RefactoringASTConsumer; + std::vector Callbacks; + ast_matchers::MatchFinder MatchFinder; + std::map &FileToReplaces; +}; + /// \brief Replace the text of the statement bound to \c FromId with the text in /// \c ToText. class ReplaceStmtWithText : public RefactoringCallback { @@ -59,6 +86,29 @@ class ReplaceStmtWithText : public RefactoringCallback { std::string ToText; }; +/// \brief Replace the text of an AST node bound to \c FromId with the result of +/// evaluating the template in \c ToTemplate. +/// +/// Expressions of the form ${NodeName} in \c ToTemplate will be +/// replaced by the text of the node bound to ${NodeName}. The string +/// "$$" will be replaced by "$". +class ReplaceNodeWithTemplate : public RefactoringCallback { +public: + static llvm::Expected> + create(StringRef FromId, StringRef ToTemplate); + void run(const ast_matchers::MatchFinder::MatchResult &Result) override; + +private: + struct TemplateElement { + enum { Literal, Identifier } Type; + std::string Value; + }; + ReplaceNodeWithTemplate(llvm::StringRef FromId, + std::vector Template); + std::string FromId; + std::vector Template; +}; + /// \brief Replace the text of the statement bound to \c FromId with the text of /// the statement bound to \c ToId. class ReplaceStmtWithStmt : public RefactoringCallback { diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 4fb6051d6f58..847638b7bbeb 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -1622,10 +1622,18 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { // We may already have a record of the same name; try to find and match it. RecordDecl *AdoptDecl = nullptr; + RecordDecl *PrevDecl = nullptr; if (!DC->isFunctionOrMethod()) { SmallVector ConflictingDecls; SmallVector FoundDecls; DC->getRedeclContext()->localUncachedLookup(SearchName, FoundDecls); + + if (!FoundDecls.empty()) { + // We're going to have to compare D against potentially conflicting Decls, so complete it. + if (D->hasExternalLexicalStorage() && !D->isCompleteDefinition()) + D->getASTContext().getExternalSource()->CompleteType(D); + } + for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) continue; @@ -1652,6 +1660,8 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { } } + PrevDecl = FoundRecord; + if (RecordDecl *FoundDef = FoundRecord->getDefinition()) { if ((SearchName && !D->isCompleteDefinition()) || (D->isCompleteDefinition() && @@ -1744,6 +1754,10 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { LexicalDC->addDeclInternal(D2); if (D->isAnonymousStructOrUnion()) D2->setAnonymousStructOrUnion(true); + if (PrevDecl) { + // FIXME: do this for all Redeclarables, not just RecordDecls. + D2->setPreviousDecl(PrevDecl); + } } Importer.Imported(D, D2); diff --git a/lib/AST/ASTStructuralEquivalence.cpp b/lib/AST/ASTStructuralEquivalence.cpp index 8fe72eac4133..9376ee1d4ee4 100644 --- a/lib/AST/ASTStructuralEquivalence.cpp +++ b/lib/AST/ASTStructuralEquivalence.cpp @@ -855,6 +855,11 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (CXXRecordDecl *D1CXX = dyn_cast(D1)) { if (CXXRecordDecl *D2CXX = dyn_cast(D2)) { + if (D1CXX->hasExternalLexicalStorage() && + !D1CXX->isCompleteDefinition()) { + D1CXX->getASTContext().getExternalSource()->CompleteType(D1CXX); + } + if (D1CXX->getNumBases() != D2CXX->getNumBases()) { if (Context.Complain) { Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent) diff --git a/lib/AST/CXXInheritance.cpp b/lib/AST/CXXInheritance.cpp index 56fb0464078f..746602d47be5 100644 --- a/lib/AST/CXXInheritance.cpp +++ b/lib/AST/CXXInheritance.cpp @@ -13,6 +13,7 @@ #include "clang/AST/CXXInheritance.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclTemplate.h" #include "clang/AST/RecordLayout.h" #include "llvm/ADT/SetVector.h" #include @@ -174,9 +175,10 @@ bool CXXRecordDecl::forallBases(ForallBasesCallback BaseMatches, return AllMatches; } -bool CXXBasePaths::lookupInBases( - ASTContext &Context, const CXXRecordDecl *Record, - CXXRecordDecl::BaseMatchesCallback BaseMatches) { +bool CXXBasePaths::lookupInBases(ASTContext &Context, + const CXXRecordDecl *Record, + CXXRecordDecl::BaseMatchesCallback BaseMatches, + bool LookupInDependent) { bool FoundPath = false; // The access of the path down to this record. @@ -194,7 +196,7 @@ bool CXXBasePaths::lookupInBases( // the base class scope is not examined during unqualified name lookup // either at the point of definition of the class template or member or // during an instantiation of the class tem- plate or member. - if (BaseType->isDependentType()) + if (!LookupInDependent && BaseType->isDependentType()) continue; // Determine whether we need to visit this base class at all, @@ -262,10 +264,28 @@ bool CXXBasePaths::lookupInBases( return FoundPath; } } else if (VisitBase) { - CXXRecordDecl *BaseRecord - = cast(BaseSpec.getType()->castAs() - ->getDecl()); - if (lookupInBases(Context, BaseRecord, BaseMatches)) { + CXXRecordDecl *BaseRecord; + if (LookupInDependent) { + BaseRecord = nullptr; + const TemplateSpecializationType *TST = + BaseSpec.getType()->getAs(); + if (!TST) { + if (auto *RT = BaseSpec.getType()->getAs()) + BaseRecord = cast(RT->getDecl()); + } else { + TemplateName TN = TST->getTemplateName(); + if (auto *TD = + dyn_cast_or_null(TN.getAsTemplateDecl())) + BaseRecord = TD->getTemplatedDecl(); + } + if (BaseRecord && !BaseRecord->hasDefinition()) + BaseRecord = nullptr; + } else { + BaseRecord = cast( + BaseSpec.getType()->castAs()->getDecl()); + } + if (BaseRecord && + lookupInBases(Context, BaseRecord, BaseMatches, LookupInDependent)) { // C++ [class.member.lookup]p2: // A member name f in one sub-object B hides a member name f in // a sub-object A if A is a base class sub-object of B. Any @@ -299,9 +319,11 @@ bool CXXBasePaths::lookupInBases( } bool CXXRecordDecl::lookupInBases(BaseMatchesCallback BaseMatches, - CXXBasePaths &Paths) const { + CXXBasePaths &Paths, + bool LookupInDependent) const { // If we didn't find anything, report that. - if (!Paths.lookupInBases(getASTContext(), this, BaseMatches)) + if (!Paths.lookupInBases(getASTContext(), this, BaseMatches, + LookupInDependent)) return false; // If we're not recording paths or we won't ever find ambiguities, @@ -387,23 +409,49 @@ bool CXXRecordDecl::FindTagMember(const CXXBaseSpecifier *Specifier, return false; } -bool CXXRecordDecl::FindOrdinaryMember(const CXXBaseSpecifier *Specifier, - CXXBasePath &Path, - DeclarationName Name) { - RecordDecl *BaseRecord = - Specifier->getType()->castAs()->getDecl(); - - const unsigned IDNS = IDNS_Ordinary | IDNS_Tag | IDNS_Member; +static bool findOrdinaryMember(RecordDecl *BaseRecord, CXXBasePath &Path, + DeclarationName Name) { + const unsigned IDNS = clang::Decl::IDNS_Ordinary | clang::Decl::IDNS_Tag | + clang::Decl::IDNS_Member; for (Path.Decls = BaseRecord->lookup(Name); !Path.Decls.empty(); Path.Decls = Path.Decls.slice(1)) { if (Path.Decls.front()->isInIdentifierNamespace(IDNS)) return true; } - + return false; } +bool CXXRecordDecl::FindOrdinaryMember(const CXXBaseSpecifier *Specifier, + CXXBasePath &Path, + DeclarationName Name) { + RecordDecl *BaseRecord = + Specifier->getType()->castAs()->getDecl(); + return findOrdinaryMember(BaseRecord, Path, Name); +} + +bool CXXRecordDecl::FindOrdinaryMemberInDependentClasses( + const CXXBaseSpecifier *Specifier, CXXBasePath &Path, + DeclarationName Name) { + const TemplateSpecializationType *TST = + Specifier->getType()->getAs(); + if (!TST) { + auto *RT = Specifier->getType()->getAs(); + if (!RT) + return false; + return findOrdinaryMember(RT->getDecl(), Path, Name); + } + TemplateName TN = TST->getTemplateName(); + const auto *TD = dyn_cast_or_null(TN.getAsTemplateDecl()); + if (!TD) + return false; + CXXRecordDecl *RD = TD->getTemplatedDecl(); + if (!RD) + return false; + return findOrdinaryMember(RD, Path, Name); +} + bool CXXRecordDecl::FindOMPReductionMember(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, DeclarationName Name) { @@ -438,6 +486,36 @@ FindNestedNameSpecifierMember(const CXXBaseSpecifier *Specifier, return false; } +std::vector CXXRecordDecl::lookupDependentName( + const DeclarationName &Name, + llvm::function_ref Filter) { + std::vector Results; + // Lookup in the class. + DeclContext::lookup_result DirectResult = lookup(Name); + if (!DirectResult.empty()) { + for (const NamedDecl *ND : DirectResult) { + if (Filter(ND)) + Results.push_back(ND); + } + return Results; + } + // Perform lookup into our base classes. + CXXBasePaths Paths; + Paths.setOrigin(this); + if (!lookupInBases( + [&](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) { + return CXXRecordDecl::FindOrdinaryMemberInDependentClasses( + Specifier, Path, Name); + }, + Paths, /*LookupInDependent=*/true)) + return Results; + for (const NamedDecl *ND : Paths.front().Decls) { + if (Filter(ND)) + Results.push_back(ND); + } + return Results; +} + void OverridingMethods::add(unsigned OverriddenSubobject, UniqueVirtualMethod Overriding) { SmallVectorImpl &SubobjectOverrides diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index dd8f768c5711..9f87fe12a9cd 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -1432,8 +1432,9 @@ bool CXXRecordDecl::isAnyDestructorNoReturn() const { // Check base classes destructor for noreturn. for (const auto &Base : bases()) - if (Base.getType()->getAsCXXRecordDecl()->isAnyDestructorNoReturn()) - return true; + if (const CXXRecordDecl *RD = Base.getType()->getAsCXXRecordDecl()) + if (RD->isAnyDestructorNoReturn()) + return true; // Check fields for noreturn. for (const auto *Field : fields()) diff --git a/lib/AST/ExternalASTMerger.cpp b/lib/AST/ExternalASTMerger.cpp index 8849cfc3c80b..1dc472a5f753 100644 --- a/lib/AST/ExternalASTMerger.cpp +++ b/lib/AST/ExternalASTMerger.cpp @@ -178,3 +178,9 @@ void ExternalASTMerger::FindExternalLexicalDecls( } }); } + +void ExternalASTMerger::CompleteType(TagDecl *Tag) { + SmallVector Result; + FindExternalLexicalDecls(Tag, [](Decl::Kind) { return true; }, Result); + Tag->setHasExternalLexicalStorage(false); +} diff --git a/lib/AST/ODRHash.cpp b/lib/AST/ODRHash.cpp index 83168d0924f6..f4d314a6dd0d 100644 --- a/lib/AST/ODRHash.cpp +++ b/lib/AST/ODRHash.cpp @@ -411,7 +411,7 @@ class ODRTypeVisitor : public TypeVisitor { void VisitTypedefType(const TypedefType *T) { AddDecl(T->getDecl()); - Hash.AddQualType(T->getDecl()->getUnderlyingType()); + AddQualType(T->getDecl()->getUnderlyingType().getCanonicalType()); VisitType(T); } }; diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp index 69e65f558f89..2367cadf645c 100644 --- a/lib/AST/Stmt.cpp +++ b/lib/AST/Stmt.cpp @@ -1112,7 +1112,7 @@ void CapturedStmt::setCapturedRegionKind(CapturedRegionKind Kind) { bool CapturedStmt::capturesVariable(const VarDecl *Var) const { for (const auto &I : captures()) { - if (!I.capturesVariable()) + if (!I.capturesVariable() && !I.capturesVariableByCopy()) continue; // This does not handle variable redeclarations. This should be diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index df26233b4796..22d52bcd3f31 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -2114,18 +2114,15 @@ bool QualType::isTriviallyCopyableType(const ASTContext &Context) const { if (hasNonTrivialObjCLifetime()) return false; - // C++11 [basic.types]p9 + // C++11 [basic.types]p9 - See Core 2094 // Scalar types, trivially copyable class types, arrays of such types, and - // non-volatile const-qualified versions of these types are collectively + // cv-qualified versions of these types are collectively // called trivially copyable types. QualType CanonicalType = getCanonicalType(); if (CanonicalType->isDependentType()) return false; - if (CanonicalType.isVolatileQualified()) - return false; - // Return false for incomplete types after skipping any incomplete array types // which are expressly allowed by the standard and thus our API. if (CanonicalType->isIncompleteType()) diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp index 33eb0b05ddcd..92c561aa9413 100644 --- a/lib/Basic/Targets.cpp +++ b/lib/Basic/Targets.cpp @@ -6862,6 +6862,11 @@ class SparcTargetInfo : public TargetInfo { case 'N': // Same as 'K' but zext (required for SIMode) case 'O': // The constant 4096 return true; + + case 'f': + case 'e': + info.setAllowsRegister(); + return true; } return false; } diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp index 0d96f2efa60a..0f07169ac8b0 100644 --- a/lib/CodeGen/BackendUtil.cpp +++ b/lib/CodeGen/BackendUtil.cpp @@ -194,6 +194,8 @@ static void addSanitizerCoveragePass(const PassManagerBuilder &Builder, // where this is not a factor). Also, on ELF this feature requires an assembler // extension that only works with -integrated-as at the moment. static bool asanUseGlobalsGC(const Triple &T, const CodeGenOptions &CGOpts) { + if (!CGOpts.SanitizeAddressGlobalsDeadStripping) + return false; switch (T.getObjectFormat()) { case Triple::MachO: case Triple::COFF: @@ -1071,7 +1073,8 @@ void clang::EmitBackendOutput(DiagnosticsEngine &Diags, // into memory and pass it into runThinLTOBackend, which will run the // function importer and invoke LTO passes. Expected> IndexOrErr = - llvm::getModuleSummaryIndexForFile(CGOpts.ThinLTOIndexFile); + llvm::getModuleSummaryIndexForFile(CGOpts.ThinLTOIndexFile, + /*IgnoreEmptyThinLTOIndexFile*/true); if (!IndexOrErr) { logAllUnhandledErrors(IndexOrErr.takeError(), errs(), "Error loading index file '" + diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp index 2b2a92dd6019..f1c20e9df1f3 100644 --- a/lib/CodeGen/CGBlocks.cpp +++ b/lib/CodeGen/CGBlocks.cpp @@ -878,7 +878,8 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) { // If type is const-qualified, copy the value into the block field. } else if (type.isConstQualified() && - type.getObjCLifetime() == Qualifiers::OCL_Strong) { + type.getObjCLifetime() == Qualifiers::OCL_Strong && + CGM.getCodeGenOpts().OptimizationLevel != 0) { llvm::Value *value = Builder.CreateLoad(src, "captured"); Builder.CreateStore(value, blockField); @@ -960,9 +961,8 @@ llvm::Type *CodeGenModule::getBlockDescriptorType() { // const char *signature; // the block signature // const char *layout; // reserved // }; - BlockDescriptorType = - llvm::StructType::create("struct.__block_descriptor", - UnsignedLongTy, UnsignedLongTy, nullptr); + BlockDescriptorType = llvm::StructType::create( + "struct.__block_descriptor", UnsignedLongTy, UnsignedLongTy); // Now form a pointer to that. unsigned AddrSpace = 0; @@ -986,9 +986,8 @@ llvm::Type *CodeGenModule::getGenericBlockLiteralType() { // struct __block_descriptor *__descriptor; // }; GenericBlockLiteralType = - llvm::StructType::create("struct.__block_literal_generic", - VoidPtrTy, IntTy, IntTy, VoidPtrTy, - BlockDescPtrTy, nullptr); + llvm::StructType::create("struct.__block_literal_generic", VoidPtrTy, + IntTy, IntTy, VoidPtrTy, BlockDescPtrTy); return GenericBlockLiteralType; } diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 2f05c0e910e5..50c9e22801c7 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -2769,6 +2769,32 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, return RValue::get(ConstantInt::get(ConvertType(E->getType()), Layout.size().getQuantity())); } + + case Builtin::BI__xray_customevent: { + if (!ShouldXRayInstrumentFunction()) + return RValue::getIgnored(); + if (const auto *XRayAttr = CurFuncDecl->getAttr()) { + if (XRayAttr->neverXRayInstrument()) + return RValue::getIgnored(); + } + Function *F = CGM.getIntrinsic(Intrinsic::xray_customevent); + auto FTy = F->getFunctionType(); + auto Arg0 = E->getArg(0); + auto Arg0Val = EmitScalarExpr(Arg0); + auto Arg0Ty = Arg0->getType(); + auto PTy0 = FTy->getParamType(0); + if (PTy0 != Arg0Val->getType()) { + if (Arg0Ty->isArrayType()) + Arg0Val = EmitArrayToPointerDecay(Arg0).getPointer(); + else + Arg0Val = Builder.CreatePointerCast(Arg0Val, PTy0); + } + auto Arg1 = EmitScalarExpr(E->getArg(1)); + auto PTy1 = FTy->getParamType(1); + if (PTy1 != Arg1->getType()) + Arg1 = Builder.CreateTruncOrBitCast(Arg1, PTy1); + return RValue::get(Builder.CreateCall(F, {Arg0Val, Arg1})); + } } // If this is an alias for a lib function (e.g. __builtin_sin), emit @@ -4545,7 +4571,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, Function *F = CGM.getIntrinsic(BuiltinID == ARM::BI__builtin_arm_stlex ? Intrinsic::arm_stlexd : Intrinsic::arm_strexd); - llvm::Type *STy = llvm::StructType::get(Int32Ty, Int32Ty, nullptr); + llvm::Type *STy = llvm::StructType::get(Int32Ty, Int32Ty); Address Tmp = CreateMemTemp(E->getArg(0)->getType()); Value *Val = EmitScalarExpr(E->getArg(0)); @@ -5375,7 +5401,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID, Function *F = CGM.getIntrinsic(BuiltinID == AArch64::BI__builtin_arm_stlex ? Intrinsic::aarch64_stlxp : Intrinsic::aarch64_stxp); - llvm::Type *STy = llvm::StructType::get(Int64Ty, Int64Ty, nullptr); + llvm::Type *STy = llvm::StructType::get(Int64Ty, Int64Ty); Address Tmp = CreateMemTemp(E->getArg(0)->getType()); EmitAnyExprToMem(E->getArg(0), Tmp, Qualifiers(), /*init*/ true); @@ -7347,8 +7373,8 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, // unsigned int __cpu_type; // unsigned int __cpu_subtype; // unsigned int __cpu_features[1]; - llvm::Type *STy = llvm::StructType::get( - Int32Ty, Int32Ty, Int32Ty, llvm::ArrayType::get(Int32Ty, 1), nullptr); + llvm::Type *STy = llvm::StructType::get(Int32Ty, Int32Ty, Int32Ty, + llvm::ArrayType::get(Int32Ty, 1)); // Grab the global __cpu_model. llvm::Constant *CpuModel = CGM.CreateRuntimeVariable(STy, "__cpu_model"); diff --git a/lib/CodeGen/CGCUDANV.cpp b/lib/CodeGen/CGCUDANV.cpp index 813cd7400186..d24ef0a8a974 100644 --- a/lib/CodeGen/CGCUDANV.cpp +++ b/lib/CodeGen/CGCUDANV.cpp @@ -265,7 +265,7 @@ llvm::Function *CGNVCUDARuntime::makeModuleCtorFunction() { "__cudaRegisterFatBinary"); // struct { int magic, int version, void * gpu_binary, void * dont_care }; llvm::StructType *FatbinWrapperTy = - llvm::StructType::get(IntTy, IntTy, VoidPtrTy, VoidPtrTy, nullptr); + llvm::StructType::get(IntTy, IntTy, VoidPtrTy, VoidPtrTy); llvm::Function *ModuleCtorFunc = llvm::Function::Create( llvm::FunctionType::get(VoidTy, VoidPtrTy, false), diff --git a/lib/CodeGen/CGCleanup.cpp b/lib/CodeGen/CGCleanup.cpp index 437ab7dd4649..e8bcf0a3ac56 100644 --- a/lib/CodeGen/CGCleanup.cpp +++ b/lib/CodeGen/CGCleanup.cpp @@ -51,8 +51,7 @@ DominatingValue::saved_type::save(CodeGenFunction &CGF, RValue rv) { if (rv.isComplex()) { CodeGenFunction::ComplexPairTy V = rv.getComplexVal(); llvm::Type *ComplexTy = - llvm::StructType::get(V.first->getType(), V.second->getType(), - (void*) nullptr); + llvm::StructType::get(V.first->getType(), V.second->getType()); Address addr = CGF.CreateDefaultAlignTempAlloca(ComplexTy, "saved-complex"); CGF.Builder.CreateStore(V.first, CGF.Builder.CreateStructGEP(addr, 0, CharUnits())); diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index 3e5434660567..9d77c61bd52c 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -209,7 +209,7 @@ llvm::DIScope *CGDebugInfo::getContextDescriptor(const Decl *Context, // Check namespace. if (const auto *NSDecl = dyn_cast(Context)) - return getOrCreateNameSpace(NSDecl); + return getOrCreateNamespace(NSDecl); if (const auto *RDecl = dyn_cast(Context)) if (!RDecl->isDependentType()) @@ -2860,8 +2860,8 @@ void CGDebugInfo::collectFunctionDeclProps(GlobalDecl GD, llvm::DIFile *Unit, if (DebugKind >= codegenoptions::LimitedDebugInfo) { if (const NamespaceDecl *NSDecl = - dyn_cast_or_null(FD->getDeclContext())) - FDContext = getOrCreateNameSpace(NSDecl); + dyn_cast_or_null(FD->getLexicalDeclContext())) + FDContext = getOrCreateNamespace(NSDecl); else if (const RecordDecl *RDecl = dyn_cast_or_null(FD->getDeclContext())) { llvm::DIScope *Mod = getParentModuleOrNull(RDecl); @@ -3961,7 +3961,7 @@ void CGDebugInfo::EmitUsingDirective(const UsingDirectiveDecl &UD) { CGM.getCodeGenOpts().DebugExplicitImport) { DBuilder.createImportedModule( getCurrentContextDescriptor(cast(UD.getDeclContext())), - getOrCreateNameSpace(NSDecl), + getOrCreateNamespace(NSDecl), getLineNumber(UD.getLocation())); } } @@ -4021,23 +4021,26 @@ CGDebugInfo::EmitNamespaceAlias(const NamespaceAliasDecl &NA) { else R = DBuilder.createImportedDeclaration( getCurrentContextDescriptor(cast(NA.getDeclContext())), - getOrCreateNameSpace(cast(NA.getAliasedNamespace())), + getOrCreateNamespace(cast(NA.getAliasedNamespace())), getLineNumber(NA.getLocation()), NA.getName()); VH.reset(R); return R; } llvm::DINamespace * -CGDebugInfo::getOrCreateNameSpace(const NamespaceDecl *NSDecl) { - NSDecl = NSDecl->getCanonicalDecl(); - auto I = NameSpaceCache.find(NSDecl); - if (I != NameSpaceCache.end()) +CGDebugInfo::getOrCreateNamespace(const NamespaceDecl *NSDecl) { + // Don't canonicalize the NamespaceDecl here: The DINamespace will be uniqued + // if necessary, and this way multiple declarations of the same namespace in + // different parent modules stay distinct. + auto I = NamespaceCache.find(NSDecl); + if (I != NamespaceCache.end()) return cast(I->second); llvm::DIScope *Context = getDeclContextDescriptor(NSDecl); + // Don't trust the context if it is a DIModule (see comment above). llvm::DINamespace *NS = DBuilder.createNameSpace(Context, NSDecl->getName(), NSDecl->isInline()); - NameSpaceCache[NSDecl].reset(NS); + NamespaceCache[NSDecl].reset(NS); return NS; } diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h index 5050ca0ad3fa..7de48f278994 100644 --- a/lib/CodeGen/CGDebugInfo.h +++ b/lib/CodeGen/CGDebugInfo.h @@ -125,7 +125,7 @@ class CGDebugInfo { /// Cache declarations relevant to DW_TAG_imported_declarations (C++ /// using declarations) that aren't covered by other more specific caches. llvm::DenseMap DeclCache; - llvm::DenseMap NameSpaceCache; + llvm::DenseMap NamespaceCache; llvm::DenseMap NamespaceAliasCache; llvm::DenseMap> @@ -194,8 +194,9 @@ class CGDebugInfo { getOrCreateFunctionType(const Decl *D, QualType FnType, llvm::DIFile *F); /// \return debug info descriptor for vtable. llvm::DIType *getOrCreateVTablePtrType(llvm::DIFile *F); + /// \return namespace descriptor for the given namespace decl. - llvm::DINamespace *getOrCreateNameSpace(const NamespaceDecl *N); + llvm::DINamespace *getOrCreateNamespace(const NamespaceDecl *N); llvm::DIType *CreatePointerLikeType(llvm::dwarf::Tag Tag, const Type *Ty, QualType PointeeTy, llvm::DIFile *F); llvm::DIType *getOrCreateStructPtrType(StringRef Name, llvm::DIType *&Cache); diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index 10a0b46d9028..0fa8eeb1c3e1 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -152,7 +152,14 @@ void CodeGenFunction::EmitDecl(const Decl &D) { /// EmitVarDecl - This method handles emission of any variable declaration /// inside a function, including static vars etc. void CodeGenFunction::EmitVarDecl(const VarDecl &D) { - if (D.isStaticLocal()) { + if (D.hasExternalStorage()) + // Don't emit it now, allow it to be emitted lazily on its first use. + return; + + // Some function-scope variable does not have static storage but still + // needs to be emitted like a static variable, e.g. a function-scope + // variable in constant address space in OpenCL. + if (D.getStorageDuration() != SD_Automatic) { llvm::GlobalValue::LinkageTypes Linkage = CGM.getLLVMLinkageVarDefinition(&D, /*isConstant=*/false); @@ -163,10 +170,6 @@ void CodeGenFunction::EmitVarDecl(const VarDecl &D) { return EmitStaticVarDecl(D, Linkage); } - if (D.hasExternalStorage()) - // Don't emit it now, allow it to be emitted lazily on its first use. - return; - if (D.getType().getAddressSpace() == LangAS::opencl_local) return CGM.getOpenCLRuntime().EmitWorkGroupLocalVarDecl(*this, D); diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp index ca1535182ec1..e65fa863fe31 100644 --- a/lib/CodeGen/CGException.cpp +++ b/lib/CodeGen/CGException.cpp @@ -765,8 +765,8 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() { llvm::BasicBlock *lpad = createBasicBlock("lpad"); EmitBlock(lpad); - llvm::LandingPadInst *LPadInst = Builder.CreateLandingPad( - llvm::StructType::get(Int8PtrTy, Int32Ty, nullptr), 0); + llvm::LandingPadInst *LPadInst = + Builder.CreateLandingPad(llvm::StructType::get(Int8PtrTy, Int32Ty), 0); llvm::Value *LPadExn = Builder.CreateExtractValue(LPadInst, 0); Builder.CreateStore(LPadExn, getExceptionSlot()); @@ -1310,8 +1310,8 @@ llvm::BasicBlock *CodeGenFunction::getTerminateLandingPad() { if (!CurFn->hasPersonalityFn()) CurFn->setPersonalityFn(getOpaquePersonalityFn(CGM, Personality)); - llvm::LandingPadInst *LPadInst = Builder.CreateLandingPad( - llvm::StructType::get(Int8PtrTy, Int32Ty, nullptr), 0); + llvm::LandingPadInst *LPadInst = + Builder.CreateLandingPad(llvm::StructType::get(Int8PtrTy, Int32Ty), 0); LPadInst->addClause(getCatchAllValue(*this)); llvm::Value *Exn = nullptr; @@ -1387,8 +1387,7 @@ llvm::BasicBlock *CodeGenFunction::getEHResumeBlock(bool isCleanup) { llvm::Value *Exn = getExceptionFromSlot(); llvm::Value *Sel = getSelectorFromSlot(); - llvm::Type *LPadType = llvm::StructType::get(Exn->getType(), - Sel->getType(), nullptr); + llvm::Type *LPadType = llvm::StructType::get(Exn->getType(), Sel->getType()); llvm::Value *LPadVal = llvm::UndefValue::get(LPadType); LPadVal = Builder.CreateInsertValue(LPadVal, Exn, 0, "lpad.val"); LPadVal = Builder.CreateInsertValue(LPadVal, Sel, 1, "lpad.val"); @@ -1747,7 +1746,7 @@ void CodeGenFunction::EmitSEHExceptionCodeSave(CodeGenFunction &ParentCGF, // }; // int exceptioncode = exception_pointers->ExceptionRecord->ExceptionCode; llvm::Type *RecordTy = CGM.Int32Ty->getPointerTo(); - llvm::Type *PtrsTy = llvm::StructType::get(RecordTy, CGM.VoidPtrTy, nullptr); + llvm::Type *PtrsTy = llvm::StructType::get(RecordTy, CGM.VoidPtrTy); llvm::Value *Ptrs = Builder.CreateBitCast(SEHInfo, PtrsTy->getPointerTo()); llvm::Value *Rec = Builder.CreateStructGEP(PtrsTy, Ptrs, 0); Rec = Builder.CreateAlignedLoad(Rec, getPointerAlign()); diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 863b4380da47..cef6292c0e4d 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -2859,9 +2859,9 @@ void CodeGenFunction::EmitCfiCheckFail() { EmitTrapCheck(DataIsNotNullPtr); llvm::StructType *SourceLocationTy = - llvm::StructType::get(VoidPtrTy, Int32Ty, Int32Ty, nullptr); + llvm::StructType::get(VoidPtrTy, Int32Ty, Int32Ty); llvm::StructType *CfiCheckFailDataTy = - llvm::StructType::get(Int8Ty, SourceLocationTy, VoidPtrTy, nullptr); + llvm::StructType::get(Int8Ty, SourceLocationTy, VoidPtrTy); llvm::Value *V = Builder.CreateConstGEP2_32( CfiCheckFailDataTy, diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp index 49bbb4808eaa..a05a088f0919 100644 --- a/lib/CodeGen/CGExprAgg.cpp +++ b/lib/CodeGen/CGExprAgg.cpp @@ -512,12 +512,20 @@ void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType, currentElement->addIncoming(element, entryBB); // Emit the actual filler expression. - LValue elementLV = - CGF.MakeAddrLValue(Address(currentElement, elementAlign), elementType); - if (filler) - EmitInitializationToLValue(filler, elementLV); - else - EmitNullInitializationToLValue(elementLV); + { + // C++1z [class.temporary]p5: + // when a default constructor is called to initialize an element of + // an array with no corresponding initializer [...] the destruction of + // every temporary created in a default argument is sequenced before + // the construction of the next array element, if any + CodeGenFunction::RunCleanupsScope CleanupsScope(CGF); + LValue elementLV = + CGF.MakeAddrLValue(Address(currentElement, elementAlign), elementType); + if (filler) + EmitInitializationToLValue(filler, elementLV); + else + EmitNullInitializationToLValue(elementLV); + } // Move on to the next element. llvm::Value *nextElement = diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp index 53c184130709..6b72774c10a5 100644 --- a/lib/CodeGen/CGExprConstant.cpp +++ b/lib/CodeGen/CGExprConstant.cpp @@ -1361,9 +1361,8 @@ llvm::Constant *CodeGenModule::EmitConstantValue(const APValue &Value, Value.getComplexIntImag()); // FIXME: the target may want to specify that this is packed. - llvm::StructType *STy = llvm::StructType::get(Complex[0]->getType(), - Complex[1]->getType(), - nullptr); + llvm::StructType *STy = + llvm::StructType::get(Complex[0]->getType(), Complex[1]->getType()); return llvm::ConstantStruct::get(STy, Complex); } case APValue::Float: { @@ -1384,9 +1383,8 @@ llvm::Constant *CodeGenModule::EmitConstantValue(const APValue &Value, Value.getComplexFloatImag()); // FIXME: the target may want to specify that this is packed. - llvm::StructType *STy = llvm::StructType::get(Complex[0]->getType(), - Complex[1]->getType(), - nullptr); + llvm::StructType *STy = + llvm::StructType::get(Complex[0]->getType(), Complex[1]->getType()); return llvm::ConstantStruct::get(STy, Complex); } case APValue::Vector: { diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index 70b741651fd1..b8d830ee9f3f 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -89,14 +89,14 @@ struct BinOpInfo { } /// Check if the binop computes a division or a remainder. - bool isDivisionLikeOperation() const { + bool isDivremOp() const { return Opcode == BO_Div || Opcode == BO_Rem || Opcode == BO_DivAssign || Opcode == BO_RemAssign; } /// Check if the binop can result in an integer division by zero. bool mayHaveIntegerDivisionByZero() const { - if (isDivisionLikeOperation()) + if (isDivremOp()) if (auto *CI = dyn_cast(RHS)) return CI->isZero(); return true; @@ -104,7 +104,7 @@ struct BinOpInfo { /// Check if the binop can result in a float division by zero. bool mayHaveFloatDivisionByZero() const { - if (isDivisionLikeOperation()) + if (isDivremOp()) if (auto *CFP = dyn_cast(RHS)) return CFP->isZero(); return true; @@ -2552,6 +2552,7 @@ Value *ScalarExprEmitter::EmitOverflowCheckedBinOp(const BinOpInfo &Ops) { if (isSigned) OpID |= 1; + CodeGenFunction::SanitizerScope SanScope(&CGF); llvm::Type *opTy = CGF.CGM.getTypes().ConvertType(Ops.Ty); llvm::Function *intrinsic = CGF.CGM.getIntrinsic(IID, opTy); @@ -2567,7 +2568,6 @@ Value *ScalarExprEmitter::EmitOverflowCheckedBinOp(const BinOpInfo &Ops) { // If the signed-integer-overflow sanitizer is enabled, emit a call to its // runtime. Otherwise, this is a -ftrapv check, so just emit a trap. if (!isSigned || CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow)) { - CodeGenFunction::SanitizerScope SanScope(&CGF); llvm::Value *NotOverflow = Builder.CreateNot(overflow); SanitizerMask Kind = isSigned ? SanitizerKind::SignedIntegerOverflow : SanitizerKind::UnsignedIntegerOverflow; diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp index 821629c50d4a..c8b8be7f4552 100644 --- a/lib/CodeGen/CGObjCGNU.cpp +++ b/lib/CodeGen/CGObjCGNU.cpp @@ -34,7 +34,6 @@ #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/Support/Compiler.h" -#include using namespace clang; using namespace CodeGen; @@ -58,18 +57,19 @@ class LazyRuntimeFunction { /// Initialises the lazy function with the name, return type, and the types /// of the arguments. - LLVM_END_WITH_NULL - void init(CodeGenModule *Mod, const char *name, llvm::Type *RetTy, ...) { + template + void init(CodeGenModule *Mod, const char *name, llvm::Type *RetTy, + Tys *... Types) { CGM = Mod; FunctionName = name; Function = nullptr; - std::vector ArgTys; - va_list Args; - va_start(Args, RetTy); - while (llvm::Type *ArgTy = va_arg(Args, llvm::Type *)) - ArgTys.push_back(ArgTy); - va_end(Args); - FTy = llvm::FunctionType::get(RetTy, ArgTys, false); + if(sizeof...(Tys)) { + SmallVector ArgTys({Types...}); + FTy = llvm::FunctionType::get(RetTy, ArgTys, false); + } + else { + FTy = llvm::FunctionType::get(RetTy, None, false); + } } llvm::FunctionType *getType() { return FTy; } @@ -603,11 +603,10 @@ class CGObjCGCC : public CGObjCGNU { public: CGObjCGCC(CodeGenModule &Mod) : CGObjCGNU(Mod, 8, 2) { // IMP objc_msg_lookup(id, SEL); - MsgLookupFn.init(&CGM, "objc_msg_lookup", IMPTy, IdTy, SelectorTy, - nullptr); + MsgLookupFn.init(&CGM, "objc_msg_lookup", IMPTy, IdTy, SelectorTy); // IMP objc_msg_lookup_super(struct objc_super*, SEL); MsgLookupSuperFn.init(&CGM, "objc_msg_lookup_super", IMPTy, - PtrToObjCSuperTy, SelectorTy, nullptr); + PtrToObjCSuperTy, SelectorTy); } }; @@ -702,52 +701,51 @@ class CGObjCGNUstep : public CGObjCGNU { CGObjCGNUstep(CodeGenModule &Mod) : CGObjCGNU(Mod, 9, 3) { const ObjCRuntime &R = CGM.getLangOpts().ObjCRuntime; - llvm::StructType *SlotStructTy = llvm::StructType::get(PtrTy, - PtrTy, PtrTy, IntTy, IMPTy, nullptr); + llvm::StructType *SlotStructTy = + llvm::StructType::get(PtrTy, PtrTy, PtrTy, IntTy, IMPTy); SlotTy = llvm::PointerType::getUnqual(SlotStructTy); // Slot_t objc_msg_lookup_sender(id *receiver, SEL selector, id sender); SlotLookupFn.init(&CGM, "objc_msg_lookup_sender", SlotTy, PtrToIdTy, - SelectorTy, IdTy, nullptr); + SelectorTy, IdTy); // Slot_t objc_msg_lookup_super(struct objc_super*, SEL); SlotLookupSuperFn.init(&CGM, "objc_slot_lookup_super", SlotTy, - PtrToObjCSuperTy, SelectorTy, nullptr); + PtrToObjCSuperTy, SelectorTy); // If we're in ObjC++ mode, then we want to make if (CGM.getLangOpts().CPlusPlus) { llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext); // void *__cxa_begin_catch(void *e) - EnterCatchFn.init(&CGM, "__cxa_begin_catch", PtrTy, PtrTy, nullptr); + EnterCatchFn.init(&CGM, "__cxa_begin_catch", PtrTy, PtrTy); // void __cxa_end_catch(void) - ExitCatchFn.init(&CGM, "__cxa_end_catch", VoidTy, nullptr); + ExitCatchFn.init(&CGM, "__cxa_end_catch", VoidTy); // void _Unwind_Resume_or_Rethrow(void*) ExceptionReThrowFn.init(&CGM, "_Unwind_Resume_or_Rethrow", VoidTy, - PtrTy, nullptr); + PtrTy); } else if (R.getVersion() >= VersionTuple(1, 7)) { llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext); // id objc_begin_catch(void *e) - EnterCatchFn.init(&CGM, "objc_begin_catch", IdTy, PtrTy, nullptr); + EnterCatchFn.init(&CGM, "objc_begin_catch", IdTy, PtrTy); // void objc_end_catch(void) - ExitCatchFn.init(&CGM, "objc_end_catch", VoidTy, nullptr); + ExitCatchFn.init(&CGM, "objc_end_catch", VoidTy); // void _Unwind_Resume_or_Rethrow(void*) - ExceptionReThrowFn.init(&CGM, "objc_exception_rethrow", VoidTy, - PtrTy, nullptr); + ExceptionReThrowFn.init(&CGM, "objc_exception_rethrow", VoidTy, PtrTy); } llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext); SetPropertyAtomic.init(&CGM, "objc_setProperty_atomic", VoidTy, IdTy, - SelectorTy, IdTy, PtrDiffTy, nullptr); + SelectorTy, IdTy, PtrDiffTy); SetPropertyAtomicCopy.init(&CGM, "objc_setProperty_atomic_copy", VoidTy, - IdTy, SelectorTy, IdTy, PtrDiffTy, nullptr); + IdTy, SelectorTy, IdTy, PtrDiffTy); SetPropertyNonAtomic.init(&CGM, "objc_setProperty_nonatomic", VoidTy, - IdTy, SelectorTy, IdTy, PtrDiffTy, nullptr); + IdTy, SelectorTy, IdTy, PtrDiffTy); SetPropertyNonAtomicCopy.init(&CGM, "objc_setProperty_nonatomic_copy", - VoidTy, IdTy, SelectorTy, IdTy, PtrDiffTy, nullptr); + VoidTy, IdTy, SelectorTy, IdTy, PtrDiffTy); // void objc_setCppObjectAtomic(void *dest, const void *src, void // *helper); CxxAtomicObjectSetFn.init(&CGM, "objc_setCppObjectAtomic", VoidTy, PtrTy, - PtrTy, PtrTy, nullptr); + PtrTy, PtrTy); // void objc_getCppObjectAtomic(void *dest, const void *src, void // *helper); CxxAtomicObjectGetFn.init(&CGM, "objc_getCppObjectAtomic", VoidTy, PtrTy, - PtrTy, PtrTy, nullptr); + PtrTy, PtrTy); } llvm::Constant *GetCppAtomicObjectGetFunction() override { @@ -849,14 +847,14 @@ class CGObjCObjFW: public CGObjCGNU { public: CGObjCObjFW(CodeGenModule &Mod): CGObjCGNU(Mod, 9, 3) { // IMP objc_msg_lookup(id, SEL); - MsgLookupFn.init(&CGM, "objc_msg_lookup", IMPTy, IdTy, SelectorTy, nullptr); + MsgLookupFn.init(&CGM, "objc_msg_lookup", IMPTy, IdTy, SelectorTy); MsgLookupFnSRet.init(&CGM, "objc_msg_lookup_stret", IMPTy, IdTy, - SelectorTy, nullptr); + SelectorTy); // IMP objc_msg_lookup_super(struct objc_super*, SEL); MsgLookupSuperFn.init(&CGM, "objc_msg_lookup_super", IMPTy, - PtrToObjCSuperTy, SelectorTy, nullptr); + PtrToObjCSuperTy, SelectorTy); MsgLookupSuperFnSRet.init(&CGM, "objc_msg_lookup_super_stret", IMPTy, - PtrToObjCSuperTy, SelectorTy, nullptr); + PtrToObjCSuperTy, SelectorTy); } }; } // end anonymous namespace @@ -945,35 +943,34 @@ CGObjCGNU::CGObjCGNU(CodeGenModule &cgm, unsigned runtimeABIVersion, } PtrToIdTy = llvm::PointerType::getUnqual(IdTy); - ObjCSuperTy = llvm::StructType::get(IdTy, IdTy, nullptr); + ObjCSuperTy = llvm::StructType::get(IdTy, IdTy); PtrToObjCSuperTy = llvm::PointerType::getUnqual(ObjCSuperTy); llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext); // void objc_exception_throw(id); - ExceptionThrowFn.init(&CGM, "objc_exception_throw", VoidTy, IdTy, nullptr); - ExceptionReThrowFn.init(&CGM, "objc_exception_throw", VoidTy, IdTy, nullptr); + ExceptionThrowFn.init(&CGM, "objc_exception_throw", VoidTy, IdTy); + ExceptionReThrowFn.init(&CGM, "objc_exception_throw", VoidTy, IdTy); // int objc_sync_enter(id); - SyncEnterFn.init(&CGM, "objc_sync_enter", IntTy, IdTy, nullptr); + SyncEnterFn.init(&CGM, "objc_sync_enter", IntTy, IdTy); // int objc_sync_exit(id); - SyncExitFn.init(&CGM, "objc_sync_exit", IntTy, IdTy, nullptr); + SyncExitFn.init(&CGM, "objc_sync_exit", IntTy, IdTy); // void objc_enumerationMutation (id) - EnumerationMutationFn.init(&CGM, "objc_enumerationMutation", VoidTy, - IdTy, nullptr); + EnumerationMutationFn.init(&CGM, "objc_enumerationMutation", VoidTy, IdTy); // id objc_getProperty(id, SEL, ptrdiff_t, BOOL) GetPropertyFn.init(&CGM, "objc_getProperty", IdTy, IdTy, SelectorTy, - PtrDiffTy, BoolTy, nullptr); + PtrDiffTy, BoolTy); // void objc_setProperty(id, SEL, ptrdiff_t, id, BOOL, BOOL) SetPropertyFn.init(&CGM, "objc_setProperty", VoidTy, IdTy, SelectorTy, - PtrDiffTy, IdTy, BoolTy, BoolTy, nullptr); + PtrDiffTy, IdTy, BoolTy, BoolTy); // void objc_setPropertyStruct(void*, void*, ptrdiff_t, BOOL, BOOL) - GetStructPropertyFn.init(&CGM, "objc_getPropertyStruct", VoidTy, PtrTy, PtrTy, - PtrDiffTy, BoolTy, BoolTy, nullptr); + GetStructPropertyFn.init(&CGM, "objc_getPropertyStruct", VoidTy, PtrTy, PtrTy, + PtrDiffTy, BoolTy, BoolTy); // void objc_setPropertyStruct(void*, void*, ptrdiff_t, BOOL, BOOL) - SetStructPropertyFn.init(&CGM, "objc_setPropertyStruct", VoidTy, PtrTy, PtrTy, - PtrDiffTy, BoolTy, BoolTy, nullptr); + SetStructPropertyFn.init(&CGM, "objc_setPropertyStruct", VoidTy, PtrTy, PtrTy, + PtrDiffTy, BoolTy, BoolTy); // IMP type llvm::Type *IMPArgs[] = { IdTy, SelectorTy }; @@ -997,21 +994,19 @@ CGObjCGNU::CGObjCGNU(CodeGenModule &cgm, unsigned runtimeABIVersion, // Get functions needed in GC mode // id objc_assign_ivar(id, id, ptrdiff_t); - IvarAssignFn.init(&CGM, "objc_assign_ivar", IdTy, IdTy, IdTy, PtrDiffTy, - nullptr); + IvarAssignFn.init(&CGM, "objc_assign_ivar", IdTy, IdTy, IdTy, PtrDiffTy); // id objc_assign_strongCast (id, id*) StrongCastAssignFn.init(&CGM, "objc_assign_strongCast", IdTy, IdTy, - PtrToIdTy, nullptr); + PtrToIdTy); // id objc_assign_global(id, id*); - GlobalAssignFn.init(&CGM, "objc_assign_global", IdTy, IdTy, PtrToIdTy, - nullptr); + GlobalAssignFn.init(&CGM, "objc_assign_global", IdTy, IdTy, PtrToIdTy); // id objc_assign_weak(id, id*); - WeakAssignFn.init(&CGM, "objc_assign_weak", IdTy, IdTy, PtrToIdTy, nullptr); + WeakAssignFn.init(&CGM, "objc_assign_weak", IdTy, IdTy, PtrToIdTy); // id objc_read_weak(id*); - WeakReadFn.init(&CGM, "objc_read_weak", IdTy, PtrToIdTy, nullptr); + WeakReadFn.init(&CGM, "objc_read_weak", IdTy, PtrToIdTy); // void *objc_memmove_collectable(void*, void *, size_t); MemMoveFn.init(&CGM, "objc_memmove_collectable", PtrTy, PtrTy, PtrTy, - SizeTy, nullptr); + SizeTy); } } @@ -1317,7 +1312,7 @@ CGObjCGNU::GenerateMessageSendSuper(CodeGenFunction &CGF, } } // Cast the pointer to a simplified version of the class structure - llvm::Type *CastTy = llvm::StructType::get(IdTy, IdTy, nullptr); + llvm::Type *CastTy = llvm::StructType::get(IdTy, IdTy); ReceiverClass = Builder.CreateBitCast(ReceiverClass, llvm::PointerType::getUnqual(CastTy)); // Get the superclass pointer @@ -1326,8 +1321,8 @@ CGObjCGNU::GenerateMessageSendSuper(CodeGenFunction &CGF, ReceiverClass = Builder.CreateAlignedLoad(ReceiverClass, CGF.getPointerAlign()); // Construct the structure used to look up the IMP - llvm::StructType *ObjCSuperTy = llvm::StructType::get( - Receiver->getType(), IdTy, nullptr); + llvm::StructType *ObjCSuperTy = + llvm::StructType::get(Receiver->getType(), IdTy); // FIXME: Is this really supposed to be a dynamic alloca? Address ObjCSuper = Address(Builder.CreateAlloca(ObjCSuperTy), @@ -1565,11 +1560,8 @@ GenerateIvarList(ArrayRef IvarNames, IvarList.addInt(IntTy, (int)IvarNames.size()); // Get the ivar structure type. - llvm::StructType *ObjCIvarTy = llvm::StructType::get( - PtrToInt8Ty, - PtrToInt8Ty, - IntTy, - nullptr); + llvm::StructType *ObjCIvarTy = + llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty, IntTy); // Array of ivar structures. auto Ivars = IvarList.beginArray(ObjCIvarTy); @@ -1611,7 +1603,7 @@ llvm::Constant *CGObjCGNU::GenerateClassStructure( // anyway; the classes will still work with the GNU runtime, they will just // be ignored. llvm::StructType *ClassTy = llvm::StructType::get( - PtrToInt8Ty, // isa + PtrToInt8Ty, // isa PtrToInt8Ty, // super_class PtrToInt8Ty, // name LongTy, // version @@ -1620,18 +1612,18 @@ llvm::Constant *CGObjCGNU::GenerateClassStructure( IVars->getType(), // ivars Methods->getType(), // methods // These are all filled in by the runtime, so we pretend - PtrTy, // dtable - PtrTy, // subclass_list - PtrTy, // sibling_class - PtrTy, // protocols - PtrTy, // gc_object_type + PtrTy, // dtable + PtrTy, // subclass_list + PtrTy, // sibling_class + PtrTy, // protocols + PtrTy, // gc_object_type // New ABI: LongTy, // abi_version IvarOffsets->getType(), // ivar_offsets Properties->getType(), // properties IntPtrTy, // strong_pointers - IntPtrTy, // weak_pointers - nullptr); + IntPtrTy // weak_pointers + ); ConstantInitBuilder Builder(CGM); auto Elements = Builder.beginStruct(ClassTy); diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index 70d24b791334..9c048423285b 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -105,8 +105,8 @@ class ObjCCommonTypesHelper { llvm::Constant *getMessageSendFp2retFn() const { llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy }; llvm::Type *longDoubleType = llvm::Type::getX86_FP80Ty(VMContext); - llvm::Type *resultType = - llvm::StructType::get(longDoubleType, longDoubleType, nullptr); + llvm::Type *resultType = + llvm::StructType::get(longDoubleType, longDoubleType); return CGM.CreateRuntimeFunction(llvm::FunctionType::get(resultType, params, true), @@ -5506,17 +5506,15 @@ ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm) // char *name; // char *attributes; // } - PropertyTy = llvm::StructType::create("struct._prop_t", - Int8PtrTy, Int8PtrTy, nullptr); + PropertyTy = llvm::StructType::create("struct._prop_t", Int8PtrTy, Int8PtrTy); // struct _prop_list_t { // uint32_t entsize; // sizeof(struct _prop_t) // uint32_t count_of_properties; // struct _prop_t prop_list[count_of_properties]; // } - PropertyListTy = - llvm::StructType::create("struct._prop_list_t", IntTy, IntTy, - llvm::ArrayType::get(PropertyTy, 0), nullptr); + PropertyListTy = llvm::StructType::create( + "struct._prop_list_t", IntTy, IntTy, llvm::ArrayType::get(PropertyTy, 0)); // struct _prop_list_t * PropertyListPtrTy = llvm::PointerType::getUnqual(PropertyListTy); @@ -5525,9 +5523,8 @@ ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm) // char *method_type; // char *_imp; // } - MethodTy = llvm::StructType::create("struct._objc_method", - SelectorPtrTy, Int8PtrTy, Int8PtrTy, - nullptr); + MethodTy = llvm::StructType::create("struct._objc_method", SelectorPtrTy, + Int8PtrTy, Int8PtrTy); // struct _objc_cache * CacheTy = llvm::StructType::create(VMContext, "struct._objc_cache"); @@ -5540,17 +5537,16 @@ ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm) // SEL name; // char *types; // } - MethodDescriptionTy = - llvm::StructType::create("struct._objc_method_description", - SelectorPtrTy, Int8PtrTy, nullptr); + MethodDescriptionTy = llvm::StructType::create( + "struct._objc_method_description", SelectorPtrTy, Int8PtrTy); // struct _objc_method_description_list { // int count; // struct _objc_method_description[1]; // } - MethodDescriptionListTy = llvm::StructType::create( - "struct._objc_method_description_list", IntTy, - llvm::ArrayType::get(MethodDescriptionTy, 0), nullptr); + MethodDescriptionListTy = + llvm::StructType::create("struct._objc_method_description_list", IntTy, + llvm::ArrayType::get(MethodDescriptionTy, 0)); // struct _objc_method_description_list * MethodDescriptionListPtrTy = @@ -5566,11 +5562,10 @@ ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm) // const char ** extendedMethodTypes; // struct _objc_property_list *class_properties; // } - ProtocolExtensionTy = - llvm::StructType::create("struct._objc_protocol_extension", - IntTy, MethodDescriptionListPtrTy, - MethodDescriptionListPtrTy, PropertyListPtrTy, - Int8PtrPtrTy, PropertyListPtrTy, nullptr); + ProtocolExtensionTy = llvm::StructType::create( + "struct._objc_protocol_extension", IntTy, MethodDescriptionListPtrTy, + MethodDescriptionListPtrTy, PropertyListPtrTy, Int8PtrPtrTy, + PropertyListPtrTy); // struct _objc_protocol_extension * ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(ProtocolExtensionTy); @@ -5582,10 +5577,8 @@ ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm) ProtocolListTy = llvm::StructType::create(VMContext, "struct._objc_protocol_list"); - ProtocolListTy->setBody(llvm::PointerType::getUnqual(ProtocolListTy), - LongTy, - llvm::ArrayType::get(ProtocolTy, 0), - nullptr); + ProtocolListTy->setBody(llvm::PointerType::getUnqual(ProtocolListTy), LongTy, + llvm::ArrayType::get(ProtocolTy, 0)); // struct _objc_protocol { // struct _objc_protocol_extension *isa; @@ -5596,9 +5589,7 @@ ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm) // } ProtocolTy->setBody(ProtocolExtensionPtrTy, Int8PtrTy, llvm::PointerType::getUnqual(ProtocolListTy), - MethodDescriptionListPtrTy, - MethodDescriptionListPtrTy, - nullptr); + MethodDescriptionListPtrTy, MethodDescriptionListPtrTy); // struct _objc_protocol_list * ProtocolListPtrTy = llvm::PointerType::getUnqual(ProtocolListTy); @@ -5612,8 +5603,8 @@ ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm) // char *ivar_type; // int ivar_offset; // } - IvarTy = llvm::StructType::create("struct._objc_ivar", - Int8PtrTy, Int8PtrTy, IntTy, nullptr); + IvarTy = llvm::StructType::create("struct._objc_ivar", Int8PtrTy, Int8PtrTy, + IntTy); // struct _objc_ivar_list * IvarListTy = @@ -5626,9 +5617,8 @@ ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm) MethodListPtrTy = llvm::PointerType::getUnqual(MethodListTy); // struct _objc_class_extension * - ClassExtensionTy = - llvm::StructType::create("struct._objc_class_extension", - IntTy, Int8PtrTy, PropertyListPtrTy, nullptr); + ClassExtensionTy = llvm::StructType::create( + "struct._objc_class_extension", IntTy, Int8PtrTy, PropertyListPtrTy); ClassExtensionPtrTy = llvm::PointerType::getUnqual(ClassExtensionTy); ClassTy = llvm::StructType::create(VMContext, "struct._objc_class"); @@ -5648,18 +5638,9 @@ ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm) // struct _objc_class_ext *ext; // }; ClassTy->setBody(llvm::PointerType::getUnqual(ClassTy), - llvm::PointerType::getUnqual(ClassTy), - Int8PtrTy, - LongTy, - LongTy, - LongTy, - IvarListPtrTy, - MethodListPtrTy, - CachePtrTy, - ProtocolListPtrTy, - Int8PtrTy, - ClassExtensionPtrTy, - nullptr); + llvm::PointerType::getUnqual(ClassTy), Int8PtrTy, LongTy, + LongTy, LongTy, IvarListPtrTy, MethodListPtrTy, CachePtrTy, + ProtocolListPtrTy, Int8PtrTy, ClassExtensionPtrTy); ClassPtrTy = llvm::PointerType::getUnqual(ClassTy); @@ -5673,12 +5654,10 @@ ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm) // struct _objc_property_list *instance_properties;// category's @property // struct _objc_property_list *class_properties; // } - CategoryTy = - llvm::StructType::create("struct._objc_category", - Int8PtrTy, Int8PtrTy, MethodListPtrTy, - MethodListPtrTy, ProtocolListPtrTy, - IntTy, PropertyListPtrTy, PropertyListPtrTy, - nullptr); + CategoryTy = llvm::StructType::create( + "struct._objc_category", Int8PtrTy, Int8PtrTy, MethodListPtrTy, + MethodListPtrTy, ProtocolListPtrTy, IntTy, PropertyListPtrTy, + PropertyListPtrTy); // Global metadata structures @@ -5689,10 +5668,9 @@ ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm) // short cat_def_cnt; // char *defs[cls_def_cnt + cat_def_cnt]; // } - SymtabTy = - llvm::StructType::create("struct._objc_symtab", - LongTy, SelectorPtrTy, ShortTy, ShortTy, - llvm::ArrayType::get(Int8PtrTy, 0), nullptr); + SymtabTy = llvm::StructType::create("struct._objc_symtab", LongTy, + SelectorPtrTy, ShortTy, ShortTy, + llvm::ArrayType::get(Int8PtrTy, 0)); SymtabPtrTy = llvm::PointerType::getUnqual(SymtabTy); // struct _objc_module { @@ -5701,10 +5679,8 @@ ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm) // char *name; // struct _objc_symtab* symtab; // } - ModuleTy = - llvm::StructType::create("struct._objc_module", - LongTy, LongTy, Int8PtrTy, SymtabPtrTy, nullptr); - + ModuleTy = llvm::StructType::create("struct._objc_module", LongTy, LongTy, + Int8PtrTy, SymtabPtrTy); // FIXME: This is the size of the setjmp buffer and should be target // specific. 18 is what's used on 32-bit X86. @@ -5713,10 +5689,9 @@ ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm) // Exceptions llvm::Type *StackPtrTy = llvm::ArrayType::get(CGM.Int8PtrTy, 4); - ExceptionDataTy = - llvm::StructType::create("struct._objc_exception_data", - llvm::ArrayType::get(CGM.Int32Ty,SetJmpBufferSize), - StackPtrTy, nullptr); + ExceptionDataTy = llvm::StructType::create( + "struct._objc_exception_data", + llvm::ArrayType::get(CGM.Int32Ty, SetJmpBufferSize), StackPtrTy); } ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm) @@ -5727,8 +5702,8 @@ ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModul // struct _objc_method method_list[method_count]; // } MethodListnfABITy = - llvm::StructType::create("struct.__method_list_t", IntTy, IntTy, - llvm::ArrayType::get(MethodTy, 0), nullptr); + llvm::StructType::create("struct.__method_list_t", IntTy, IntTy, + llvm::ArrayType::get(MethodTy, 0)); // struct method_list_t * MethodListnfABIPtrTy = llvm::PointerType::getUnqual(MethodListnfABITy); @@ -5752,14 +5727,12 @@ ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModul ProtocolListnfABITy = llvm::StructType::create(VMContext, "struct._objc_protocol_list"); - ProtocolnfABITy = - llvm::StructType::create("struct._protocol_t", ObjectPtrTy, Int8PtrTy, - llvm::PointerType::getUnqual(ProtocolListnfABITy), - MethodListnfABIPtrTy, MethodListnfABIPtrTy, - MethodListnfABIPtrTy, MethodListnfABIPtrTy, - PropertyListPtrTy, IntTy, IntTy, Int8PtrPtrTy, - Int8PtrTy, PropertyListPtrTy, - nullptr); + ProtocolnfABITy = llvm::StructType::create( + "struct._protocol_t", ObjectPtrTy, Int8PtrTy, + llvm::PointerType::getUnqual(ProtocolListnfABITy), MethodListnfABIPtrTy, + MethodListnfABIPtrTy, MethodListnfABIPtrTy, MethodListnfABIPtrTy, + PropertyListPtrTy, IntTy, IntTy, Int8PtrPtrTy, Int8PtrTy, + PropertyListPtrTy); // struct _protocol_t* ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolnfABITy); @@ -5769,8 +5742,7 @@ ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModul // struct _protocol_t *[protocol_count]; // } ProtocolListnfABITy->setBody(LongTy, - llvm::ArrayType::get(ProtocolnfABIPtrTy, 0), - nullptr); + llvm::ArrayType::get(ProtocolnfABIPtrTy, 0)); // struct _objc_protocol_list* ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolListnfABITy); @@ -5784,7 +5756,7 @@ ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModul // } IvarnfABITy = llvm::StructType::create( "struct._ivar_t", llvm::PointerType::getUnqual(IvarOffsetVarTy), - Int8PtrTy, Int8PtrTy, IntTy, IntTy, nullptr); + Int8PtrTy, Int8PtrTy, IntTy, IntTy); // struct _ivar_list_t { // uint32 entsize; // sizeof(struct _ivar_t) @@ -5792,8 +5764,8 @@ ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModul // struct _iver_t list[count]; // } IvarListnfABITy = - llvm::StructType::create("struct._ivar_list_t", IntTy, IntTy, - llvm::ArrayType::get(IvarnfABITy, 0), nullptr); + llvm::StructType::create("struct._ivar_list_t", IntTy, IntTy, + llvm::ArrayType::get(IvarnfABITy, 0)); IvarListnfABIPtrTy = llvm::PointerType::getUnqual(IvarListnfABITy); @@ -5812,13 +5784,10 @@ ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModul // } // FIXME. Add 'reserved' field in 64bit abi mode! - ClassRonfABITy = llvm::StructType::create("struct._class_ro_t", - IntTy, IntTy, IntTy, Int8PtrTy, - Int8PtrTy, MethodListnfABIPtrTy, - ProtocolListnfABIPtrTy, - IvarListnfABIPtrTy, - Int8PtrTy, PropertyListPtrTy, - nullptr); + ClassRonfABITy = llvm::StructType::create( + "struct._class_ro_t", IntTy, IntTy, IntTy, Int8PtrTy, Int8PtrTy, + MethodListnfABIPtrTy, ProtocolListnfABIPtrTy, IvarListnfABIPtrTy, + Int8PtrTy, PropertyListPtrTy); // ImpnfABITy - LLVM for id (*)(id, SEL, ...) llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy }; @@ -5835,11 +5804,9 @@ ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModul ClassnfABITy = llvm::StructType::create(VMContext, "struct._class_t"); ClassnfABITy->setBody(llvm::PointerType::getUnqual(ClassnfABITy), - llvm::PointerType::getUnqual(ClassnfABITy), - CachePtrTy, + llvm::PointerType::getUnqual(ClassnfABITy), CachePtrTy, llvm::PointerType::getUnqual(ImpnfABITy), - llvm::PointerType::getUnqual(ClassRonfABITy), - nullptr); + llvm::PointerType::getUnqual(ClassRonfABITy)); // LLVM for struct _class_t * ClassnfABIPtrTy = llvm::PointerType::getUnqual(ClassnfABITy); @@ -5854,15 +5821,10 @@ ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModul // const struct _prop_list_t * const class_properties; // const uint32_t size; // } - CategorynfABITy = llvm::StructType::create("struct._category_t", - Int8PtrTy, ClassnfABIPtrTy, - MethodListnfABIPtrTy, - MethodListnfABIPtrTy, - ProtocolListnfABIPtrTy, - PropertyListPtrTy, - PropertyListPtrTy, - IntTy, - nullptr); + CategorynfABITy = llvm::StructType::create( + "struct._category_t", Int8PtrTy, ClassnfABIPtrTy, MethodListnfABIPtrTy, + MethodListnfABIPtrTy, ProtocolListnfABIPtrTy, PropertyListPtrTy, + PropertyListPtrTy, IntTy); // New types for nonfragile abi messaging. CodeGen::CodeGenTypes &Types = CGM.getTypes(); @@ -5899,9 +5861,8 @@ ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModul // SUPER_IMP messenger; // SEL name; // }; - SuperMessageRefTy = - llvm::StructType::create("struct._super_message_ref_t", - ImpnfABITy, SelectorPtrTy, nullptr); + SuperMessageRefTy = llvm::StructType::create("struct._super_message_ref_t", + ImpnfABITy, SelectorPtrTy); // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t* SuperMessageRefPtrTy = llvm::PointerType::getUnqual(SuperMessageRefTy); @@ -5912,10 +5873,9 @@ ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModul // const char* name; // c++ typeinfo string // Class cls; // }; - EHTypeTy = - llvm::StructType::create("struct._objc_typeinfo", - llvm::PointerType::getUnqual(Int8PtrTy), - Int8PtrTy, ClassnfABIPtrTy, nullptr); + EHTypeTy = llvm::StructType::create("struct._objc_typeinfo", + llvm::PointerType::getUnqual(Int8PtrTy), + Int8PtrTy, ClassnfABIPtrTy); EHTypePtrTy = llvm::PointerType::getUnqual(EHTypeTy); } diff --git a/lib/CodeGen/CGOpenMPRuntime.cpp b/lib/CodeGen/CGOpenMPRuntime.cpp index d1a706b8821e..b256a88c47ad 100644 --- a/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/lib/CodeGen/CGOpenMPRuntime.cpp @@ -728,7 +728,7 @@ CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM) IdentTy = llvm::StructType::create( "ident_t", CGM.Int32Ty /* reserved_1 */, CGM.Int32Ty /* flags */, CGM.Int32Ty /* reserved_2 */, CGM.Int32Ty /* reserved_3 */, - CGM.Int8PtrTy /* psource */, nullptr); + CGM.Int8PtrTy /* psource */); KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8); loadOffloadInfoMetadata(); diff --git a/lib/CodeGen/CodeGenAction.cpp b/lib/CodeGen/CodeGenAction.cpp index f57cbe86c413..c7e30fad7575 100644 --- a/lib/CodeGen/CodeGenAction.cpp +++ b/lib/CodeGen/CodeGenAction.cpp @@ -548,9 +548,9 @@ void BackendConsumer::UnsupportedDiagHandler( StringRef Filename; unsigned Line, Column; - bool BadDebugInfo; - FullSourceLoc Loc = getBestLocationFromDebugLoc(D, BadDebugInfo, Filename, - Line, Column); + bool BadDebugInfo = false; + FullSourceLoc Loc = + getBestLocationFromDebugLoc(D, BadDebugInfo, Filename, Line, Column); Diags.Report(Loc, diag::err_fe_backend_unsupported) << D.getMessage().str(); @@ -572,8 +572,8 @@ void BackendConsumer::EmitOptimizationMessage( StringRef Filename; unsigned Line, Column; bool BadDebugInfo = false; - FullSourceLoc Loc = getBestLocationFromDebugLoc(D, BadDebugInfo, Filename, - Line, Column); + FullSourceLoc Loc = + getBestLocationFromDebugLoc(D, BadDebugInfo, Filename, Line, Column); std::string Msg; raw_string_ostream MsgStream(Msg); diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index ff26d80fe2b6..a0254797ea43 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -751,7 +751,7 @@ void CodeGenModule::EmitCtorList(CtorList &Fns, const char *GlobalName) { // Get the type of a ctor entry, { i32, void ()*, i8* }. llvm::StructType *CtorStructTy = llvm::StructType::get( - Int32Ty, llvm::PointerType::getUnqual(CtorFTy), VoidPtrTy, nullptr); + Int32Ty, llvm::PointerType::getUnqual(CtorFTy), VoidPtrTy); // Construct the constructor and destructor arrays. ConstantInitBuilder builder(*this); diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp index dc24b2040f04..5ed929135880 100644 --- a/lib/CodeGen/CodeGenTypes.cpp +++ b/lib/CodeGen/CodeGenTypes.cpp @@ -490,7 +490,7 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) { llvm_unreachable("Unexpected undeduced type!"); case Type::Complex: { llvm::Type *EltTy = ConvertType(cast(Ty)->getElementType()); - ResultType = llvm::StructType::get(EltTy, EltTy, nullptr); + ResultType = llvm::StructType::get(EltTy, EltTy); break; } case Type::LValueReference: diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp index dac2d15fa406..66f51305430a 100644 --- a/lib/CodeGen/ItaniumCXXABI.cpp +++ b/lib/CodeGen/ItaniumCXXABI.cpp @@ -499,7 +499,7 @@ llvm::Type * ItaniumCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) { if (MPT->isMemberDataPointer()) return CGM.PtrDiffTy; - return llvm::StructType::get(CGM.PtrDiffTy, CGM.PtrDiffTy, nullptr); + return llvm::StructType::get(CGM.PtrDiffTy, CGM.PtrDiffTy); } /// In the Itanium and ARM ABIs, method pointers have the form: diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp index 4ebbef7dfb5b..18367d1602ba 100644 --- a/lib/CodeGen/TargetInfo.cpp +++ b/lib/CodeGen/TargetInfo.cpp @@ -3159,8 +3159,7 @@ GetX86_64ByValArgumentPair(llvm::Type *Lo, llvm::Type *Hi, } } - llvm::StructType *Result = llvm::StructType::get(Lo, Hi, nullptr); - + llvm::StructType *Result = llvm::StructType::get(Lo, Hi); // Verify that the second element is at an 8-byte offset. assert(TD.getStructLayout(Result)->getElementOffset(1) == 8 && @@ -3235,8 +3234,7 @@ classifyReturnType(QualType RetTy) const { case ComplexX87: assert(Hi == ComplexX87 && "Unexpected ComplexX87 classification."); ResType = llvm::StructType::get(llvm::Type::getX86_FP80Ty(getVMContext()), - llvm::Type::getX86_FP80Ty(getVMContext()), - nullptr); + llvm::Type::getX86_FP80Ty(getVMContext())); break; } @@ -3732,7 +3730,7 @@ Address X86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, CGF.Builder.CreateConstInBoundsByteGEP(RegAddrLo, CharUnits::fromQuantity(16)); llvm::Type *DoubleTy = CGF.DoubleTy; - llvm::StructType *ST = llvm::StructType::get(DoubleTy, DoubleTy, nullptr); + llvm::StructType *ST = llvm::StructType::get(DoubleTy, DoubleTy); llvm::Value *V; Address Tmp = CGF.CreateMemTemp(Ty); Tmp = CGF.Builder.CreateElementBitCast(Tmp, ST); @@ -4637,7 +4635,7 @@ PPC64_SVR4_ABIInfo::classifyReturnType(QualType RetTy) const { llvm::Type *CoerceTy; if (Bits > GPRBits) { CoerceTy = llvm::IntegerType::get(getVMContext(), GPRBits); - CoerceTy = llvm::StructType::get(CoerceTy, CoerceTy, nullptr); + CoerceTy = llvm::StructType::get(CoerceTy, CoerceTy); } else CoerceTy = llvm::IntegerType::get(getVMContext(), llvm::alignTo(Bits, 8)); @@ -6695,6 +6693,14 @@ MipsABIInfo::classifyArgumentType(QualType Ty, uint64_t &Offset) const { return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory); } + // Use indirect if the aggregate cannot fit into registers for + // passing arguments according to the ABI + unsigned Threshold = IsO32 ? 16 : 64; + + if(getContext().getTypeSizeInChars(Ty) > CharUnits::fromQuantity(Threshold)) + return ABIArgInfo::getIndirect(CharUnits::fromQuantity(Align), true, + getContext().getTypeAlign(Ty) / 8 > Align); + // If we have reached here, aggregates are passed directly by coercing to // another structure type. Padding is inserted if the offset of the // aggregate is unaligned. @@ -7037,13 +7043,13 @@ ABIArgInfo HexagonABIInfo::classifyArgumentType(QualType Ty) const { ABIArgInfo::getExtend() : ABIArgInfo::getDirect()); } + if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) + return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory); + // Ignore empty records. if (isEmptyRecord(getContext(), Ty, true)) return ABIArgInfo::getIgnore(); - if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) - return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory); - uint64_t Size = getContext().getTypeSize(Ty); if (Size > 64) return getNaturalAlignIndirect(Ty, /*ByVal=*/true); diff --git a/lib/Driver/SanitizerArgs.cpp b/lib/Driver/SanitizerArgs.cpp index c298302c477c..9ab2e176845c 100644 --- a/lib/Driver/SanitizerArgs.cpp +++ b/lib/Driver/SanitizerArgs.cpp @@ -563,12 +563,18 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, } } - if (Arg *A = Args.getLastArg( - options::OPT_fsanitize_address_use_after_scope, - options::OPT_fno_sanitize_address_use_after_scope)) { - AsanUseAfterScope = A->getOption().getID() == - options::OPT_fsanitize_address_use_after_scope; - } + AsanUseAfterScope = Args.hasFlag( + options::OPT_fsanitize_address_use_after_scope, + options::OPT_fno_sanitize_address_use_after_scope, AsanUseAfterScope); + + // As a workaround for a bug in gold 2.26 and earlier, dead stripping of + // globals in ASan is disabled by default on ELF targets. + // See https://sourceware.org/bugzilla/show_bug.cgi?id=19002 + AsanGlobalsDeadStripping = + !TC.getTriple().isOSBinFormatELF() || + Args.hasArg(options::OPT_fsanitize_address_globals_dead_stripping); + } else { + AsanUseAfterScope = false; } // Parse -link-cxx-sanitizer flag. @@ -634,7 +640,7 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, std::make_pair(CoverageNoPrune, "-fsanitize-coverage-no-prune")}; for (auto F : CoverageFlags) { if (CoverageFeatures & F.first) - CmdArgs.push_back(Args.MakeArgString(F.second)); + CmdArgs.push_back(F.second); } if (TC.getTriple().isOSWindows() && needsUbsanRt()) { @@ -687,7 +693,7 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, llvm::utostr(MsanTrackOrigins))); if (MsanUseAfterDtor) - CmdArgs.push_back(Args.MakeArgString("-fsanitize-memory-use-after-dtor")); + CmdArgs.push_back("-fsanitize-memory-use-after-dtor"); // FIXME: Pass these parameters as function attributes, not as -llvm flags. if (!TsanMemoryAccess) { @@ -706,17 +712,20 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, } if (CfiCrossDso) - CmdArgs.push_back(Args.MakeArgString("-fsanitize-cfi-cross-dso")); + CmdArgs.push_back("-fsanitize-cfi-cross-dso"); if (Stats) - CmdArgs.push_back(Args.MakeArgString("-fsanitize-stats")); + CmdArgs.push_back("-fsanitize-stats"); if (AsanFieldPadding) CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-field-padding=" + llvm::utostr(AsanFieldPadding))); if (AsanUseAfterScope) - CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-use-after-scope")); + CmdArgs.push_back("-fsanitize-address-use-after-scope"); + + if (AsanGlobalsDeadStripping) + CmdArgs.push_back("-fsanitize-address-globals-dead-stripping"); // MSan: Workaround for PR16386. // ASan: This is mainly to help LSan with cases such as @@ -724,7 +733,7 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, // We can't make this conditional on -fsanitize=leak, as that flag shouldn't // affect compilation. if (Sanitizers.has(Memory) || Sanitizers.has(Address)) - CmdArgs.push_back(Args.MakeArgString("-fno-assume-sane-operator-new")); + CmdArgs.push_back("-fno-assume-sane-operator-new"); // Require -fvisibility= flag on non-Windows when compiling if vptr CFI is // enabled. diff --git a/lib/Driver/ToolChains/Arch/Mips.cpp b/lib/Driver/ToolChains/Arch/Mips.cpp index cd791af83220..f33542477fb5 100644 --- a/lib/Driver/ToolChains/Arch/Mips.cpp +++ b/lib/Driver/ToolChains/Arch/Mips.cpp @@ -282,18 +282,18 @@ void mips::getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple, if (Arg *A = Args.getLastArg(options::OPT_mfp32, options::OPT_mfpxx, options::OPT_mfp64)) { if (A->getOption().matches(options::OPT_mfp32)) - Features.push_back(Args.MakeArgString("-fp64")); + Features.push_back("-fp64"); else if (A->getOption().matches(options::OPT_mfpxx)) { - Features.push_back(Args.MakeArgString("+fpxx")); - Features.push_back(Args.MakeArgString("+nooddspreg")); + Features.push_back("+fpxx"); + Features.push_back("+nooddspreg"); } else - Features.push_back(Args.MakeArgString("+fp64")); + Features.push_back("+fp64"); } else if (mips::shouldUseFPXX(Args, Triple, CPUName, ABIName, FloatABI)) { - Features.push_back(Args.MakeArgString("+fpxx")); - Features.push_back(Args.MakeArgString("+nooddspreg")); + Features.push_back("+fpxx"); + Features.push_back("+nooddspreg"); } else if (mips::isFP64ADefault(Triple, CPUName)) { - Features.push_back(Args.MakeArgString("+fp64")); - Features.push_back(Args.MakeArgString("+nooddspreg")); + Features.push_back("+fp64"); + Features.push_back("+nooddspreg"); } AddTargetFeature(Args, Features, options::OPT_mno_odd_spreg, diff --git a/lib/Driver/ToolChains/Myriad.cpp b/lib/Driver/ToolChains/Myriad.cpp index 2935755c12be..f70ce93c45ce 100644 --- a/lib/Driver/ToolChains/Myriad.cpp +++ b/lib/Driver/ToolChains/Myriad.cpp @@ -43,15 +43,17 @@ void tools::SHAVE::Compiler::ConstructJob(Compilation &C, const JobAction &JA, } CmdArgs.push_back("-DMYRIAD2"); - // Append all -I, -iquote, -isystem paths, defines/undefines, - // 'f' flags, optimize flags, and warning options. + // Append all -I, -iquote, -isystem paths, defines/undefines, 'f' + // flags, 'g' flags, 'M' flags, optimize flags, warning options, + // mcpu flags, mllvm flags, and Xclang flags. // These are spelled the same way in clang and moviCompile. Args.AddAllArgsExcept( CmdArgs, {options::OPT_I_Group, options::OPT_clang_i_Group, options::OPT_std_EQ, options::OPT_D, options::OPT_U, options::OPT_f_Group, options::OPT_f_clang_Group, options::OPT_g_Group, options::OPT_M_Group, - options::OPT_O_Group, options::OPT_W_Group, options::OPT_mcpu_EQ}, + options::OPT_O_Group, options::OPT_W_Group, options::OPT_mcpu_EQ, + options::OPT_mllvm, options::OPT_Xclang}, {options::OPT_fno_split_dwarf_inlining}); Args.hasArg(options::OPT_fno_split_dwarf_inlining); // Claim it if present. diff --git a/lib/Driver/ToolChains/WebAssembly.cpp b/lib/Driver/ToolChains/WebAssembly.cpp index 123a1516f1e7..3471569b6884 100644 --- a/lib/Driver/ToolChains/WebAssembly.cpp +++ b/lib/Driver/ToolChains/WebAssembly.cpp @@ -42,7 +42,7 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA, const char *Linker = Args.MakeArgString(ToolChain.GetLinkerPath()); ArgStringList CmdArgs; CmdArgs.push_back("-flavor"); - CmdArgs.push_back("ld"); + CmdArgs.push_back("wasm"); // Enable garbage collection of unused input sections by default, since code // size is of particular importance. This is significantly facilitated by @@ -101,6 +101,9 @@ WebAssembly::WebAssembly(const Driver &D, const llvm::Triple &Triple, : ToolChain(D, Triple, Args) { assert(Triple.isArch32Bit() != Triple.isArch64Bit()); + + getProgramPaths().push_back(getDriver().getInstalledDir()); + getFilePaths().push_back( getDriver().SysRoot + "/lib" + (Triple.isArch32Bit() ? "32" : "64")); } diff --git a/lib/Format/ContinuationIndenter.cpp b/lib/Format/ContinuationIndenter.cpp index 3adb72c11da8..488f9dd582f9 100644 --- a/lib/Format/ContinuationIndenter.cpp +++ b/lib/Format/ContinuationIndenter.cpp @@ -674,6 +674,8 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) { return State.Stack[State.Stack.size() - 2].LastSpace; return State.FirstIndent; } + if (Current.is(tok::r_paren) && State.Stack.size() > 1) + return State.Stack[State.Stack.size() - 2].LastSpace; if (NextNonComment->is(TT_TemplateString) && NextNonComment->closesScope()) return State.Stack[State.Stack.size() - 2].LastSpace; if (Current.is(tok::identifier) && Current.Next && @@ -920,6 +922,10 @@ void ContinuationIndenter::moveStatePastFakeLParens(LineState &State, NewParenState.NoLineBreak = NewParenState.NoLineBreak || State.Stack.back().NoLineBreakInOperand; + // Don't propagate AvoidBinPacking into subexpressions of arg/param lists. + if (*I > prec::Comma) + NewParenState.AvoidBinPacking = false; + // Indent from 'LastSpace' unless these are fake parentheses encapsulating // a builder type call after 'return' or, if the alignment after opening // brackets is disabled. @@ -1034,13 +1040,20 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State, NestedBlockIndent = Column; } + bool EndsInComma = + Current.MatchingParen && + Current.MatchingParen->getPreviousNonComment() && + Current.MatchingParen->getPreviousNonComment()->is(tok::comma); + AvoidBinPacking = + (Style.Language == FormatStyle::LK_JavaScript && EndsInComma) || (State.Line->MustBeDeclaration && !Style.BinPackParameters) || (!State.Line->MustBeDeclaration && !Style.BinPackArguments) || (Style.ExperimentalAutoDetectBinPacking && (Current.PackingKind == PPK_OnePerLine || (!BinPackInconclusiveFunctions && Current.PackingKind == PPK_Inconclusive))); + if (Current.is(TT_ObjCMethodExpr) && Current.MatchingParen) { if (Style.ColumnLimit) { // If this '[' opens an ObjC call, determine whether all parameters fit @@ -1061,6 +1074,9 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State, } } } + + if (Style.Language == FormatStyle::LK_JavaScript && EndsInComma) + BreakBeforeParameter = true; } // Generally inherit NoLineBreak from the current scope to nested scope. // However, don't do this for non-empty nested blocks, dict literals and diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp index f55a623a8d1f..c8677e805179 100644 --- a/lib/Format/Format.cpp +++ b/lib/Format/Format.cpp @@ -171,6 +171,18 @@ template <> struct ScalarEnumerationTraits { } }; +template <> struct ScalarEnumerationTraits { + static void enumeration(IO &IO, FormatStyle::EscapedNewlineAlignmentStyle &Value) { + IO.enumCase(Value, "DontAlign", FormatStyle::ENAS_DontAlign); + IO.enumCase(Value, "Left", FormatStyle::ENAS_Left); + IO.enumCase(Value, "Right", FormatStyle::ENAS_Right); + + // For backward compatibility. + IO.enumCase(Value, "true", FormatStyle::ENAS_Left); + IO.enumCase(Value, "false", FormatStyle::ENAS_Right); + } +}; + template <> struct ScalarEnumerationTraits { static void enumeration(IO &IO, FormatStyle::PointerAlignmentStyle &Value) { IO.enumCase(Value, "Middle", FormatStyle::PAS_Middle); @@ -233,6 +245,7 @@ template <> struct MappingTraits { // For backward compatibility. if (!IO.outputting()) { + IO.mapOptional("AlignEscapedNewlinesLeft", Style.AlignEscapedNewlines); IO.mapOptional("DerivePointerBinding", Style.DerivePointerAlignment); IO.mapOptional("IndentFunctionDeclarationAfterType", Style.IndentWrappedFunctionNames); @@ -247,7 +260,7 @@ template <> struct MappingTraits { Style.AlignConsecutiveAssignments); IO.mapOptional("AlignConsecutiveDeclarations", Style.AlignConsecutiveDeclarations); - IO.mapOptional("AlignEscapedNewlinesLeft", Style.AlignEscapedNewlinesLeft); + IO.mapOptional("AlignEscapedNewlines", Style.AlignEscapedNewlines); IO.mapOptional("AlignOperands", Style.AlignOperands); IO.mapOptional("AlignTrailingComments", Style.AlignTrailingComments); IO.mapOptional("AllowAllParametersOfDeclarationOnNextLine", @@ -498,7 +511,7 @@ FormatStyle getLLVMStyle() { FormatStyle LLVMStyle; LLVMStyle.Language = FormatStyle::LK_Cpp; LLVMStyle.AccessModifierOffset = -2; - LLVMStyle.AlignEscapedNewlinesLeft = false; + LLVMStyle.AlignEscapedNewlines = FormatStyle::ENAS_Right; LLVMStyle.AlignAfterOpenBracket = FormatStyle::BAS_Align; LLVMStyle.AlignOperands = true; LLVMStyle.AlignTrailingComments = true; @@ -587,7 +600,7 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) { GoogleStyle.Language = Language; GoogleStyle.AccessModifierOffset = -1; - GoogleStyle.AlignEscapedNewlinesLeft = true; + GoogleStyle.AlignEscapedNewlines = FormatStyle::ENAS_Left; GoogleStyle.AllowShortIfStatementsOnASingleLine = true; GoogleStyle.AllowShortLoopsOnASingleLine = true; GoogleStyle.AlwaysBreakBeforeMultilineStrings = true; @@ -624,9 +637,10 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) { GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; GoogleStyle.BreakBeforeTernaryOperators = false; - // taze:, @tag followed by { for a lot of JSDoc tags, and @see, which is - // commonly followed by overlong URLs. - GoogleStyle.CommentPragmas = "(taze:|(@[A-Za-z_0-9-]+[ \\t]*{)|@see)"; + // taze:, triple slash directives (`/// <...`), @tag followed by { for a lot + // of JSDoc tags, and @see, which is commonly followed by overlong URLs. + GoogleStyle.CommentPragmas = + "(taze:|^/[ \t]*<|(@[A-Za-z_0-9-]+[ \\t]*{)|@see)"; GoogleStyle.MaxEmptyLinesToKeep = 3; GoogleStyle.NamespaceIndentation = FormatStyle::NI_All; GoogleStyle.SpacesInContainerLiterals = false; diff --git a/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp index c274d7bf07f8..387768a6ee56 100644 --- a/lib/Format/TokenAnnotator.cpp +++ b/lib/Format/TokenAnnotator.cpp @@ -576,9 +576,12 @@ class AnnotatingParser { } break; case tok::kw_for: - if (Style.Language == FormatStyle::LK_JavaScript && Tok->Previous && - Tok->Previous->is(tok::period)) - break; + if (Style.Language == FormatStyle::LK_JavaScript) + if (Tok->Previous && Tok->Previous->is(tok::period)) + break; + // JS' for async ( ... + if (CurrentToken->is(Keywords.kw_async)) + next(); Contexts.back().ColonIsForRangeExpr = true; next(); if (!parseParens()) @@ -1034,8 +1037,9 @@ class AnnotatingParser { if (Style.Language == FormatStyle::LK_JavaScript) { if (Current.is(tok::exclaim)) { if (Current.Previous && - (Current.Previous->isOneOf(tok::identifier, tok::r_paren, - tok::r_square, tok::r_brace) || + (Current.Previous->isOneOf(tok::identifier, tok::kw_namespace, + tok::r_paren, tok::r_square, + tok::r_brace) || Current.Previous->Tok.isLiteral())) { Current.Type = TT_JsNonNullAssertion; return; @@ -2248,6 +2252,10 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line, } else if (Style.Language == FormatStyle::LK_JavaScript) { if (Left.is(TT_JsFatArrow)) return true; + // for async ( ... + if (Right.is(tok::l_paren) && Left.is(Keywords.kw_async) && + Left.Previous && Left.Previous->is(tok::kw_for)) + return true; if (Left.is(Keywords.kw_async) && Right.is(tok::l_paren) && Right.MatchingParen) { const FormatToken *Next = Right.MatchingParen->getNextNonComment(); @@ -2462,16 +2470,20 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line, return true; } - // If the last token before a '}' is a comma or a trailing comment, the - // intention is to insert a line break after it in order to make shuffling - // around entries easier. + // If the last token before a '}', ']', or ')' is a comma or a trailing + // comment, the intention is to insert a line break after it in order to make + // shuffling around entries easier. const FormatToken *BeforeClosingBrace = nullptr; - if (Left.isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) && + if ((Left.isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) || + (Style.Language == FormatStyle::LK_JavaScript && + Left.is(tok::l_paren))) && Left.BlockKind != BK_Block && Left.MatchingParen) BeforeClosingBrace = Left.MatchingParen->Previous; else if (Right.MatchingParen && - Right.MatchingParen->isOneOf(tok::l_brace, - TT_ArrayInitializerLSquare)) + (Right.MatchingParen->isOneOf(tok::l_brace, + TT_ArrayInitializerLSquare) || + (Style.Language == FormatStyle::LK_JavaScript && + Right.MatchingParen->is(tok::l_paren)))) BeforeClosingBrace = &Left; if (BeforeClosingBrace && (BeforeClosingBrace->is(tok::comma) || BeforeClosingBrace->isTrailingComment())) diff --git a/lib/Format/UnwrappedLineParser.cpp b/lib/Format/UnwrappedLineParser.cpp index 2d788b52dfda..31c66ffb00a1 100644 --- a/lib/Format/UnwrappedLineParser.cpp +++ b/lib/Format/UnwrappedLineParser.cpp @@ -368,9 +368,10 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) { (Style.Language == FormatStyle::LK_JavaScript && NextTok->isOneOf(Keywords.kw_of, Keywords.kw_in, Keywords.kw_as)) || + (Style.isCpp() && NextTok->is(tok::l_paren)) || NextTok->isOneOf(tok::comma, tok::period, tok::colon, tok::r_paren, tok::r_square, tok::l_brace, - tok::l_square, tok::l_paren, tok::ellipsis) || + tok::l_square, tok::ellipsis) || (NextTok->is(tok::identifier) && !PrevTok->isOneOf(tok::semi, tok::r_brace, tok::l_brace)) || (NextTok->is(tok::semi) && @@ -476,6 +477,24 @@ static bool isGoogScope(const UnwrappedLine &Line) { return I->Tok->is(tok::l_paren); } +static bool isIIFE(const UnwrappedLine &Line, + const AdditionalKeywords &Keywords) { + // Look for the start of an immediately invoked anonymous function. + // https://en.wikipedia.org/wiki/Immediately-invoked_function_expression + // This is commonly done in JavaScript to create a new, anonymous scope. + // Example: (function() { ... })() + if (Line.Tokens.size() < 3) + return false; + auto I = Line.Tokens.begin(); + if (I->Tok->isNot(tok::l_paren)) + return false; + ++I; + if (I->Tok->isNot(Keywords.kw_function)) + return false; + ++I; + return I->Tok->is(tok::l_paren); +} + static bool ShouldBreakBeforeBrace(const FormatStyle &Style, const FormatToken &InitialToken) { if (InitialToken.is(tok::kw_namespace)) @@ -493,15 +512,16 @@ void UnwrappedLineParser::parseChildBlock() { FormatTok->BlockKind = BK_Block; nextToken(); { - bool GoogScope = - Style.Language == FormatStyle::LK_JavaScript && isGoogScope(*Line); + bool SkipIndent = + (Style.Language == FormatStyle::LK_JavaScript && + (isGoogScope(*Line) || isIIFE(*Line, Keywords))); ScopedLineState LineState(*this); ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack, /*MustBeDeclaration=*/false); - Line->Level += GoogScope ? 0 : 1; + Line->Level += SkipIndent ? 0 : 1; parseLevel(/*HasOpeningBrace=*/true); flushComments(isOnNewLine(*FormatTok)); - Line->Level -= GoogScope ? 0 : 1; + Line->Level -= SkipIndent ? 0 : 1; } nextToken(); } @@ -1615,6 +1635,10 @@ void UnwrappedLineParser::parseForOrWhileLoop() { assert(FormatTok->isOneOf(tok::kw_for, tok::kw_while, TT_ForEachMacro) && "'for', 'while' or foreach macro expected"); nextToken(); + // JS' for async ( ... + if (Style.Language == FormatStyle::LK_JavaScript && + FormatTok->is(Keywords.kw_async)) + nextToken(); if (FormatTok->Tok.is(tok::l_paren)) parseParens(); if (FormatTok->Tok.is(tok::l_brace)) { diff --git a/lib/Format/WhitespaceManager.cpp b/lib/Format/WhitespaceManager.cpp index 2c1f59324971..3b6311d15487 100644 --- a/lib/Format/WhitespaceManager.cpp +++ b/lib/Format/WhitespaceManager.cpp @@ -517,8 +517,11 @@ void WhitespaceManager::alignTrailingComments(unsigned Start, unsigned End, } void WhitespaceManager::alignEscapedNewlines() { - unsigned MaxEndOfLine = - Style.AlignEscapedNewlinesLeft ? 0 : Style.ColumnLimit; + if (Style.AlignEscapedNewlines == FormatStyle::ENAS_DontAlign) + return; + + bool AlignLeft = Style.AlignEscapedNewlines == FormatStyle::ENAS_Left; + unsigned MaxEndOfLine = AlignLeft ? 0 : Style.ColumnLimit; unsigned StartOfMacro = 0; for (unsigned i = 1, e = Changes.size(); i < e; ++i) { Change &C = Changes[i]; @@ -527,7 +530,7 @@ void WhitespaceManager::alignEscapedNewlines() { MaxEndOfLine = std::max(C.PreviousEndOfTokenColumn + 2, MaxEndOfLine); } else { alignEscapedNewlines(StartOfMacro + 1, i, MaxEndOfLine); - MaxEndOfLine = Style.AlignEscapedNewlinesLeft ? 0 : Style.ColumnLimit; + MaxEndOfLine = AlignLeft ? 0 : Style.ColumnLimit; StartOfMacro = i; } } @@ -602,7 +605,7 @@ void WhitespaceManager::appendNewlineText(std::string &Text, unsigned Newlines, unsigned EscapedNewlineColumn) { if (Newlines > 0) { unsigned Offset = - std::min(EscapedNewlineColumn - 1, PreviousEndOfTokenColumn); + std::min(EscapedNewlineColumn - 2, PreviousEndOfTokenColumn); for (unsigned i = 0; i < Newlines; ++i) { Text.append(EscapedNewlineColumn - Offset - 1, ' '); Text.append(UseCRLF ? "\\\r\n" : "\\\n"); diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 96854b8fbc1a..51147b6f9499 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -778,6 +778,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.SanitizeAddressUseAfterScope = A->getOption().getID() == OPT_fsanitize_address_use_after_scope; } + Opts.SanitizeAddressGlobalsDeadStripping = + Args.hasArg(OPT_fsanitize_address_globals_dead_stripping); Opts.SSPBufferSize = getLastArgIntValue(Args, OPT_stack_protector_buffer_size, 8, Diags); Opts.StackRealignment = Args.hasArg(OPT_mstackrealign); diff --git a/lib/Headers/avxintrin.h b/lib/Headers/avxintrin.h index cdb7aa4fb626..15d28259dcc0 100644 --- a/lib/Headers/avxintrin.h +++ b/lib/Headers/avxintrin.h @@ -1458,12 +1458,13 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c) /// \brief Computes two dot products in parallel, using the lower and upper /// halves of two [8 x float] vectors as input to the two computations, and /// returning the two dot products in the lower and upper halves of the -/// [8 x float] result. The immediate integer operand controls which input -/// elements will contribute to the dot product, and where the final results -/// are returned. In general, for each dot product, the four corresponding -/// elements of the input vectors are multiplied; the first two and second -/// two products are summed, then the two sums are added to form the final -/// result. +/// [8 x float] result. +/// +/// The immediate integer operand controls which input elements will +/// contribute to the dot product, and where the final results are returned. +/// In general, for each dot product, the four corresponding elements of the +/// input vectors are multiplied; the first two and second two products are +/// summed, then the two sums are added to form the final result. /// /// \headerfile /// @@ -1497,15 +1498,16 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c) /* Vector shuffle */ /// \brief Selects 8 float values from the 256-bit operands of [8 x float], as -/// specified by the immediate value operand. The four selected elements in -/// each operand are copied to the destination according to the bits -/// specified in the immediate operand. The selected elements from the first -/// 256-bit operand are copied to bits [63:0] and bits [191:128] of the -/// destination, and the selected elements from the second 256-bit operand -/// are copied to bits [127:64] and bits [255:192] of the destination. For -/// example, if bits [7:0] of the immediate operand contain a value of 0xFF, -/// the 256-bit destination vector would contain the following values: b[7], -/// b[7], a[7], a[7], b[3], b[3], a[3], a[3]. +/// specified by the immediate value operand. +/// +/// The four selected elements in each operand are copied to the destination +/// according to the bits specified in the immediate operand. The selected +/// elements from the first 256-bit operand are copied to bits [63:0] and +/// bits [191:128] of the destination, and the selected elements from the +/// second 256-bit operand are copied to bits [127:64] and bits [255:192] of +/// the destination. For example, if bits [7:0] of the immediate operand +/// contain a value of 0xFF, the 256-bit destination vector would contain the +/// following values: b[7], b[7], a[7], a[7], b[3], b[3], a[3], a[3]. /// /// \headerfile /// @@ -1557,13 +1559,14 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c) 12 + (((mask) >> 6) & 0x3)); }) /// \brief Selects four double-precision values from the 256-bit operands of -/// [4 x double], as specified by the immediate value operand. The selected -/// elements from the first 256-bit operand are copied to bits [63:0] and -/// bits [191:128] in the destination, and the selected elements from the -/// second 256-bit operand are copied to bits [127:64] and bits [255:192] in -/// the destination. For example, if bits [3:0] of the immediate operand -/// contain a value of 0xF, the 256-bit destination vector would contain the -/// following values: b[3], a[3], b[1], a[1]. +/// [4 x double], as specified by the immediate value operand. +/// +/// The selected elements from the first 256-bit operand are copied to bits +/// [63:0] and bits [191:128] in the destination, and the selected elements +/// from the second 256-bit operand are copied to bits [127:64] and bits +/// [255:192] in the destination. For example, if bits [3:0] of the immediate +/// operand contain a value of 0xF, the 256-bit destination vector would +/// contain the following values: b[3], a[3], b[1], a[1]. /// /// \headerfile /// @@ -1641,9 +1644,11 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c) /// \brief Compares each of the corresponding double-precision values of two /// 128-bit vectors of [2 x double], using the operation specified by the -/// immediate integer operand. Returns a [2 x double] vector consisting of -/// two doubles corresponding to the two comparison results: zero if the -/// comparison is false, and all 1's if the comparison is true. +/// immediate integer operand. +/// +/// Returns a [2 x double] vector consisting of two doubles corresponding to +/// the two comparison results: zero if the comparison is false, and all 1's +/// if the comparison is true. /// /// \headerfile /// @@ -1699,9 +1704,11 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c) /// \brief Compares each of the corresponding values of two 128-bit vectors of /// [4 x float], using the operation specified by the immediate integer -/// operand. Returns a [4 x float] vector consisting of four floats -/// corresponding to the four comparison results: zero if the comparison is -/// false, and all 1's if the comparison is true. +/// operand. +/// +/// Returns a [4 x float] vector consisting of four floats corresponding to +/// the four comparison results: zero if the comparison is false, and all 1's +/// if the comparison is true. /// /// \headerfile /// @@ -1757,9 +1764,11 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c) /// \brief Compares each of the corresponding double-precision values of two /// 256-bit vectors of [4 x double], using the operation specified by the -/// immediate integer operand. Returns a [4 x double] vector consisting of -/// four doubles corresponding to the four comparison results: zero if the -/// comparison is false, and all 1's if the comparison is true. +/// immediate integer operand. +/// +/// Returns a [4 x double] vector consisting of four doubles corresponding to +/// the four comparison results: zero if the comparison is false, and all 1's +/// if the comparison is true. /// /// \headerfile /// @@ -1815,9 +1824,11 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c) /// \brief Compares each of the corresponding values of two 256-bit vectors of /// [8 x float], using the operation specified by the immediate integer -/// operand. Returns a [8 x float] vector consisting of eight floats -/// corresponding to the eight comparison results: zero if the comparison is -/// false, and all 1's if the comparison is true. +/// operand. +/// +/// Returns a [8 x float] vector consisting of eight floats corresponding to +/// the eight comparison results: zero if the comparison is false, and all +/// 1's if the comparison is true. /// /// \headerfile /// @@ -1873,8 +1884,10 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c) /// \brief Compares each of the corresponding scalar double-precision values of /// two 128-bit vectors of [2 x double], using the operation specified by the -/// immediate integer operand. If the result is true, all 64 bits of the -/// destination vector are set; otherwise they are cleared. +/// immediate integer operand. +/// +/// If the result is true, all 64 bits of the destination vector are set; +/// otherwise they are cleared. /// /// \headerfile /// @@ -1930,8 +1943,10 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c) /// \brief Compares each of the corresponding scalar values of two 128-bit /// vectors of [4 x float], using the operation specified by the immediate -/// integer operand. If the result is true, all 32 bits of the destination -/// vector are set; otherwise they are cleared. +/// integer operand. +/// +/// If the result is true, all 32 bits of the destination vector are set; +/// otherwise they are cleared. /// /// \headerfile /// @@ -2536,7 +2551,9 @@ _mm256_unpacklo_ps(__m256 __a, __m256 __b) /// \brief Given two 128-bit floating-point vectors of [2 x double], perform an /// element-by-element comparison of the double-precision element in the /// first source vector and the corresponding element in the second source -/// vector. The EFLAGS register is updated as follows: \n +/// vector. +/// +/// The EFLAGS register is updated as follows: \n /// If there is at least one pair of double-precision elements where the /// sign-bits of both elements are 1, the ZF flag is set to 0. Otherwise the /// ZF flag is set to 1. \n @@ -2563,7 +2580,9 @@ _mm_testz_pd(__m128d __a, __m128d __b) /// \brief Given two 128-bit floating-point vectors of [2 x double], perform an /// element-by-element comparison of the double-precision element in the /// first source vector and the corresponding element in the second source -/// vector. The EFLAGS register is updated as follows: \n +/// vector. +/// +/// The EFLAGS register is updated as follows: \n /// If there is at least one pair of double-precision elements where the /// sign-bits of both elements are 1, the ZF flag is set to 0. Otherwise the /// ZF flag is set to 1. \n @@ -2590,7 +2609,9 @@ _mm_testc_pd(__m128d __a, __m128d __b) /// \brief Given two 128-bit floating-point vectors of [2 x double], perform an /// element-by-element comparison of the double-precision element in the /// first source vector and the corresponding element in the second source -/// vector. The EFLAGS register is updated as follows: \n +/// vector. +/// +/// The EFLAGS register is updated as follows: \n /// If there is at least one pair of double-precision elements where the /// sign-bits of both elements are 1, the ZF flag is set to 0. Otherwise the /// ZF flag is set to 1. \n @@ -2618,7 +2639,9 @@ _mm_testnzc_pd(__m128d __a, __m128d __b) /// \brief Given two 128-bit floating-point vectors of [4 x float], perform an /// element-by-element comparison of the single-precision element in the /// first source vector and the corresponding element in the second source -/// vector. The EFLAGS register is updated as follows: \n +/// vector. +/// +/// The EFLAGS register is updated as follows: \n /// If there is at least one pair of single-precision elements where the /// sign-bits of both elements are 1, the ZF flag is set to 0. Otherwise the /// ZF flag is set to 1. \n @@ -2645,7 +2668,9 @@ _mm_testz_ps(__m128 __a, __m128 __b) /// \brief Given two 128-bit floating-point vectors of [4 x float], perform an /// element-by-element comparison of the single-precision element in the /// first source vector and the corresponding element in the second source -/// vector. The EFLAGS register is updated as follows: \n +/// vector. +/// +/// The EFLAGS register is updated as follows: \n /// If there is at least one pair of single-precision elements where the /// sign-bits of both elements are 1, the ZF flag is set to 0. Otherwise the /// ZF flag is set to 1. \n @@ -2672,7 +2697,9 @@ _mm_testc_ps(__m128 __a, __m128 __b) /// \brief Given two 128-bit floating-point vectors of [4 x float], perform an /// element-by-element comparison of the single-precision element in the /// first source vector and the corresponding element in the second source -/// vector. The EFLAGS register is updated as follows: \n +/// vector. +/// +/// The EFLAGS register is updated as follows: \n /// If there is at least one pair of single-precision elements where the /// sign-bits of both elements are 1, the ZF flag is set to 0. Otherwise the /// ZF flag is set to 1. \n @@ -2700,7 +2727,9 @@ _mm_testnzc_ps(__m128 __a, __m128 __b) /// \brief Given two 256-bit floating-point vectors of [4 x double], perform an /// element-by-element comparison of the double-precision elements in the /// first source vector and the corresponding elements in the second source -/// vector. The EFLAGS register is updated as follows: \n +/// vector. +/// +/// The EFLAGS register is updated as follows: \n /// If there is at least one pair of double-precision elements where the /// sign-bits of both elements are 1, the ZF flag is set to 0. Otherwise the /// ZF flag is set to 1. \n @@ -2727,7 +2756,9 @@ _mm256_testz_pd(__m256d __a, __m256d __b) /// \brief Given two 256-bit floating-point vectors of [4 x double], perform an /// element-by-element comparison of the double-precision elements in the /// first source vector and the corresponding elements in the second source -/// vector. The EFLAGS register is updated as follows: \n +/// vector. +/// +/// The EFLAGS register is updated as follows: \n /// If there is at least one pair of double-precision elements where the /// sign-bits of both elements are 1, the ZF flag is set to 0. Otherwise the /// ZF flag is set to 1. \n @@ -2754,7 +2785,9 @@ _mm256_testc_pd(__m256d __a, __m256d __b) /// \brief Given two 256-bit floating-point vectors of [4 x double], perform an /// element-by-element comparison of the double-precision elements in the /// first source vector and the corresponding elements in the second source -/// vector. The EFLAGS register is updated as follows: \n +/// vector. +/// +/// The EFLAGS register is updated as follows: \n /// If there is at least one pair of double-precision elements where the /// sign-bits of both elements are 1, the ZF flag is set to 0. Otherwise the /// ZF flag is set to 1. \n @@ -2782,7 +2815,9 @@ _mm256_testnzc_pd(__m256d __a, __m256d __b) /// \brief Given two 256-bit floating-point vectors of [8 x float], perform an /// element-by-element comparison of the single-precision element in the /// first source vector and the corresponding element in the second source -/// vector. The EFLAGS register is updated as follows: \n +/// vector. +/// +/// The EFLAGS register is updated as follows: \n /// If there is at least one pair of single-precision elements where the /// sign-bits of both elements are 1, the ZF flag is set to 0. Otherwise the /// ZF flag is set to 1. \n @@ -2809,7 +2844,9 @@ _mm256_testz_ps(__m256 __a, __m256 __b) /// \brief Given two 256-bit floating-point vectors of [8 x float], perform an /// element-by-element comparison of the single-precision element in the /// first source vector and the corresponding element in the second source -/// vector. The EFLAGS register is updated as follows: \n +/// vector. +/// +/// The EFLAGS register is updated as follows: \n /// If there is at least one pair of single-precision elements where the /// sign-bits of both elements are 1, the ZF flag is set to 0. Otherwise the /// ZF flag is set to 1. \n @@ -2836,7 +2873,9 @@ _mm256_testc_ps(__m256 __a, __m256 __b) /// \brief Given two 256-bit floating-point vectors of [8 x float], perform an /// element-by-element comparison of the single-precision elements in the /// first source vector and the corresponding elements in the second source -/// vector. The EFLAGS register is updated as follows: \n +/// vector. +/// +/// The EFLAGS register is updated as follows: \n /// If there is at least one pair of single-precision elements where the /// sign-bits of both elements are 1, the ZF flag is set to 0. Otherwise the /// ZF flag is set to 1. \n @@ -2862,7 +2901,9 @@ _mm256_testnzc_ps(__m256 __a, __m256 __b) } /// \brief Given two 256-bit integer vectors, perform a bit-by-bit comparison -/// of the two source vectors and update the EFLAGS register as follows: \n +/// of the two source vectors. +/// +/// The EFLAGS register is updated as follows: \n /// If there is at least one pair of bits where both bits are 1, the ZF flag /// is set to 0. Otherwise the ZF flag is set to 1. \n /// If there is at least one pair of bits where the bit from the first source @@ -2886,7 +2927,9 @@ _mm256_testz_si256(__m256i __a, __m256i __b) } /// \brief Given two 256-bit integer vectors, perform a bit-by-bit comparison -/// of the two source vectors and update the EFLAGS register as follows: \n +/// of the two source vectors. +/// +/// The EFLAGS register is updated as follows: \n /// If there is at least one pair of bits where both bits are 1, the ZF flag /// is set to 0. Otherwise the ZF flag is set to 1. \n /// If there is at least one pair of bits where the bit from the first source @@ -2910,7 +2953,9 @@ _mm256_testc_si256(__m256i __a, __m256i __b) } /// \brief Given two 256-bit integer vectors, perform a bit-by-bit comparison -/// of the two source vectors and update the EFLAGS register as follows: \n +/// of the two source vectors. +/// +/// The EFLAGS register is updated as follows: \n /// If there is at least one pair of bits where both bits are 1, the ZF flag /// is set to 0. Otherwise the ZF flag is set to 1. \n /// If there is at least one pair of bits where the bit from the first source @@ -4466,9 +4511,10 @@ _mm256_castsi256_si128(__m256i __a) } /// \brief Constructs a 256-bit floating-point vector of [4 x double] from a -/// 128-bit floating-point vector of [2 x double]. The lower 128 bits -/// contain the value of the source vector. The contents of the upper 128 -/// bits are undefined. +/// 128-bit floating-point vector of [2 x double]. +/// +/// The lower 128 bits contain the value of the source vector. The contents +/// of the upper 128 bits are undefined. /// /// \headerfile /// @@ -4486,9 +4532,10 @@ _mm256_castpd128_pd256(__m128d __a) } /// \brief Constructs a 256-bit floating-point vector of [8 x float] from a -/// 128-bit floating-point vector of [4 x float]. The lower 128 bits contain -/// the value of the source vector. The contents of the upper 128 bits are -/// undefined. +/// 128-bit floating-point vector of [4 x float]. +/// +/// The lower 128 bits contain the value of the source vector. The contents +/// of the upper 128 bits are undefined. /// /// \headerfile /// @@ -4506,6 +4553,7 @@ _mm256_castps128_ps256(__m128 __a) } /// \brief Constructs a 256-bit integer vector from a 128-bit integer vector. +/// /// The lower 128 bits contain the value of the source vector. The contents /// of the upper 128 bits are undefined. /// @@ -4586,8 +4634,10 @@ _mm256_zextsi128_si256(__m128i __a) /// \brief Constructs a new 256-bit vector of [8 x float] by first duplicating /// a 256-bit vector of [8 x float] given in the first parameter, and then /// replacing either the upper or the lower 128 bits with the contents of a -/// 128-bit vector of [4 x float] in the second parameter. The immediate -/// integer parameter determines between the upper or the lower 128 bits. +/// 128-bit vector of [4 x float] in the second parameter. +/// +/// The immediate integer parameter determines between the upper or the lower +/// 128 bits. /// /// \headerfile /// @@ -4631,8 +4681,10 @@ _mm256_zextsi128_si256(__m128i __a) /// \brief Constructs a new 256-bit vector of [4 x double] by first duplicating /// a 256-bit vector of [4 x double] given in the first parameter, and then /// replacing either the upper or the lower 128 bits with the contents of a -/// 128-bit vector of [2 x double] in the second parameter. The immediate -/// integer parameter determines between the upper or the lower 128 bits. +/// 128-bit vector of [2 x double] in the second parameter. +/// +/// The immediate integer parameter determines between the upper or the lower +/// 128 bits. /// /// \headerfile /// @@ -4672,8 +4724,10 @@ _mm256_zextsi128_si256(__m128i __a) /// \brief Constructs a new 256-bit integer vector by first duplicating a /// 256-bit integer vector given in the first parameter, and then replacing /// either the upper or the lower 128 bits with the contents of a 128-bit -/// integer vector in the second parameter. The immediate integer parameter -/// determines between the upper or the lower 128 bits. +/// integer vector in the second parameter. +/// +/// The immediate integer parameter determines between the upper or the lower +/// 128 bits. /// /// \headerfile /// diff --git a/lib/Headers/emmintrin.h b/lib/Headers/emmintrin.h index 13b0db22ec44..fa5cefadc52c 100644 --- a/lib/Headers/emmintrin.h +++ b/lib/Headers/emmintrin.h @@ -462,8 +462,9 @@ _mm_cmplt_pd(__m128d __a, __m128d __b) /// \brief Compares each of the corresponding double-precision values of the /// 128-bit vectors of [2 x double] to determine if the values in the first -/// operand are less than or equal to those in the second operand. Each -/// comparison yields 0h for false, FFFFFFFFFFFFFFFFh for true. +/// operand are less than or equal to those in the second operand. +/// +/// Each comparison yields 0h for false, FFFFFFFFFFFFFFFFh for true. /// /// \headerfile /// @@ -482,8 +483,9 @@ _mm_cmple_pd(__m128d __a, __m128d __b) /// \brief Compares each of the corresponding double-precision values of the /// 128-bit vectors of [2 x double] to determine if the values in the first -/// operand are greater than those in the second operand. Each comparison -/// yields 0h for false, FFFFFFFFFFFFFFFFh for true. +/// operand are greater than those in the second operand. +/// +/// Each comparison yields 0h for false, FFFFFFFFFFFFFFFFh for true. /// /// \headerfile /// @@ -502,8 +504,9 @@ _mm_cmpgt_pd(__m128d __a, __m128d __b) /// \brief Compares each of the corresponding double-precision values of the /// 128-bit vectors of [2 x double] to determine if the values in the first -/// operand are greater than or equal to those in the second operand. Each -/// comparison yields 0h for false, FFFFFFFFFFFFFFFFh for true. +/// operand are greater than or equal to those in the second operand. +/// +/// Each comparison yields 0h for false, FFFFFFFFFFFFFFFFh for true. /// /// \headerfile /// @@ -522,9 +525,10 @@ _mm_cmpge_pd(__m128d __a, __m128d __b) /// \brief Compares each of the corresponding double-precision values of the /// 128-bit vectors of [2 x double] to determine if the values in the first -/// operand are ordered with respect to those in the second operand. A pair -/// of double-precision values are "ordered" with respect to each other if -/// neither value is a NaN. Each comparison yields 0h for false, +/// operand are ordered with respect to those in the second operand. +/// +/// A pair of double-precision values are "ordered" with respect to each +/// other if neither value is a NaN. Each comparison yields 0h for false, /// FFFFFFFFFFFFFFFFh for true. /// /// \headerfile @@ -544,9 +548,10 @@ _mm_cmpord_pd(__m128d __a, __m128d __b) /// \brief Compares each of the corresponding double-precision values of the /// 128-bit vectors of [2 x double] to determine if the values in the first -/// operand are unordered with respect to those in the second operand. A pair -/// of double-precision values are "unordered" with respect to each other if -/// one or both values are NaN. Each comparison yields 0h for false, +/// operand are unordered with respect to those in the second operand. +/// +/// A pair of double-precision values are "unordered" with respect to each +/// other if one or both values are NaN. Each comparison yields 0h for false, /// FFFFFFFFFFFFFFFFh for true. /// /// \headerfile @@ -567,8 +572,9 @@ _mm_cmpunord_pd(__m128d __a, __m128d __b) /// \brief Compares each of the corresponding double-precision values of the /// 128-bit vectors of [2 x double] to determine if the values in the first -/// operand are unequal to those in the second operand. Each comparison -/// yields 0h for false, FFFFFFFFFFFFFFFFh for true. +/// operand are unequal to those in the second operand. +/// +/// Each comparison yields 0h for false, FFFFFFFFFFFFFFFFh for true. /// /// \headerfile /// @@ -587,8 +593,9 @@ _mm_cmpneq_pd(__m128d __a, __m128d __b) /// \brief Compares each of the corresponding double-precision values of the /// 128-bit vectors of [2 x double] to determine if the values in the first -/// operand are not less than those in the second operand. Each comparison -/// yields 0h for false, FFFFFFFFFFFFFFFFh for true. +/// operand are not less than those in the second operand. +/// +/// Each comparison yields 0h for false, FFFFFFFFFFFFFFFFh for true. /// /// \headerfile /// @@ -607,8 +614,9 @@ _mm_cmpnlt_pd(__m128d __a, __m128d __b) /// \brief Compares each of the corresponding double-precision values of the /// 128-bit vectors of [2 x double] to determine if the values in the first -/// operand are not less than or equal to those in the second operand. Each -/// comparison yields 0h for false, FFFFFFFFFFFFFFFFh for true. +/// operand are not less than or equal to those in the second operand. +/// +/// Each comparison yields 0h for false, FFFFFFFFFFFFFFFFh for true. /// /// \headerfile /// @@ -627,8 +635,9 @@ _mm_cmpnle_pd(__m128d __a, __m128d __b) /// \brief Compares each of the corresponding double-precision values of the /// 128-bit vectors of [2 x double] to determine if the values in the first -/// operand are not greater than those in the second operand. Each -/// comparison yields 0h for false, FFFFFFFFFFFFFFFFh for true. +/// operand are not greater than those in the second operand. +/// +/// Each comparison yields 0h for false, FFFFFFFFFFFFFFFFh for true. /// /// \headerfile /// @@ -648,6 +657,7 @@ _mm_cmpngt_pd(__m128d __a, __m128d __b) /// \brief Compares each of the corresponding double-precision values of the /// 128-bit vectors of [2 x double] to determine if the values in the first /// operand are not greater than or equal to those in the second operand. +/// /// Each comparison yields 0h for false, FFFFFFFFFFFFFFFFh for true. /// /// \headerfile @@ -666,8 +676,9 @@ _mm_cmpnge_pd(__m128d __a, __m128d __b) } /// \brief Compares the lower double-precision floating-point values in each of -/// the two 128-bit floating-point vectors of [2 x double] for equality. The -/// comparison yields 0h for false, FFFFFFFFFFFFFFFFh for true. +/// the two 128-bit floating-point vectors of [2 x double] for equality. +/// +/// The comparison yields 0h for false, FFFFFFFFFFFFFFFFh for true. /// /// \headerfile /// @@ -690,8 +701,9 @@ _mm_cmpeq_sd(__m128d __a, __m128d __b) /// \brief Compares the lower double-precision floating-point values in each of /// the two 128-bit floating-point vectors of [2 x double] to determine if /// the value in the first parameter is less than the corresponding value in -/// the second parameter. The comparison yields 0h for false, -/// FFFFFFFFFFFFFFFFh for true. +/// the second parameter. +/// +/// The comparison yields 0h for false, FFFFFFFFFFFFFFFFh for true. /// /// \headerfile /// @@ -714,8 +726,9 @@ _mm_cmplt_sd(__m128d __a, __m128d __b) /// \brief Compares the lower double-precision floating-point values in each of /// the two 128-bit floating-point vectors of [2 x double] to determine if /// the value in the first parameter is less than or equal to the -/// corresponding value in the second parameter. The comparison yields 0h for -/// false, FFFFFFFFFFFFFFFFh for true. +/// corresponding value in the second parameter. +/// +/// The comparison yields 0h for false, FFFFFFFFFFFFFFFFh for true. /// /// \headerfile /// @@ -738,8 +751,9 @@ _mm_cmple_sd(__m128d __a, __m128d __b) /// \brief Compares the lower double-precision floating-point values in each of /// the two 128-bit floating-point vectors of [2 x double] to determine if /// the value in the first parameter is greater than the corresponding value -/// in the second parameter. The comparison yields 0h for false, -/// FFFFFFFFFFFFFFFFh for true. +/// in the second parameter. +/// +/// The comparison yields 0h for false, FFFFFFFFFFFFFFFFh for true. /// /// \headerfile /// @@ -763,8 +777,9 @@ _mm_cmpgt_sd(__m128d __a, __m128d __b) /// \brief Compares the lower double-precision floating-point values in each of /// the two 128-bit floating-point vectors of [2 x double] to determine if /// the value in the first parameter is greater than or equal to the -/// corresponding value in the second parameter. The comparison yields 0h for -/// false, FFFFFFFFFFFFFFFFh for true. +/// corresponding value in the second parameter. +/// +/// The comparison yields 0h for false, FFFFFFFFFFFFFFFFh for true. /// /// \headerfile /// @@ -788,9 +803,11 @@ _mm_cmpge_sd(__m128d __a, __m128d __b) /// \brief Compares the lower double-precision floating-point values in each of /// the two 128-bit floating-point vectors of [2 x double] to determine if /// the value in the first parameter is "ordered" with respect to the -/// corresponding value in the second parameter. The comparison yields 0h for -/// false, FFFFFFFFFFFFFFFFh for true. A pair of double-precision values are -/// "ordered" with respect to each other if neither value is a NaN. +/// corresponding value in the second parameter. +/// +/// The comparison yields 0h for false, FFFFFFFFFFFFFFFFh for true. A pair of +/// double-precision values are "ordered" with respect to each other if +/// neither value is a NaN. /// /// \headerfile /// @@ -813,9 +830,11 @@ _mm_cmpord_sd(__m128d __a, __m128d __b) /// \brief Compares the lower double-precision floating-point values in each of /// the two 128-bit floating-point vectors of [2 x double] to determine if /// the value in the first parameter is "unordered" with respect to the -/// corresponding value in the second parameter. The comparison yields 0h -/// for false, FFFFFFFFFFFFFFFFh for true. A pair of double-precision values -/// are "unordered" with respect to each other if one or both values are NaN. +/// corresponding value in the second parameter. +/// +/// The comparison yields 0h for false, FFFFFFFFFFFFFFFFh for true. A pair of +/// double-precision values are "unordered" with respect to each other if one +/// or both values are NaN. /// /// \headerfile /// @@ -839,8 +858,9 @@ _mm_cmpunord_sd(__m128d __a, __m128d __b) /// \brief Compares the lower double-precision floating-point values in each of /// the two 128-bit floating-point vectors of [2 x double] to determine if /// the value in the first parameter is unequal to the corresponding value in -/// the second parameter. The comparison yields 0h for false, -/// FFFFFFFFFFFFFFFFh for true. +/// the second parameter. +/// +/// The comparison yields 0h for false, FFFFFFFFFFFFFFFFh for true. /// /// \headerfile /// @@ -863,8 +883,9 @@ _mm_cmpneq_sd(__m128d __a, __m128d __b) /// \brief Compares the lower double-precision floating-point values in each of /// the two 128-bit floating-point vectors of [2 x double] to determine if /// the value in the first parameter is not less than the corresponding -/// value in the second parameter. The comparison yields 0h for false, -/// FFFFFFFFFFFFFFFFh for true. +/// value in the second parameter. +/// +/// The comparison yields 0h for false, FFFFFFFFFFFFFFFFh for true. /// /// \headerfile /// @@ -887,8 +908,9 @@ _mm_cmpnlt_sd(__m128d __a, __m128d __b) /// \brief Compares the lower double-precision floating-point values in each of /// the two 128-bit floating-point vectors of [2 x double] to determine if /// the value in the first parameter is not less than or equal to the -/// corresponding value in the second parameter. The comparison yields 0h -/// for false, FFFFFFFFFFFFFFFFh for true. +/// corresponding value in the second parameter. +/// +/// The comparison yields 0h for false, FFFFFFFFFFFFFFFFh for true. /// /// \headerfile /// @@ -911,8 +933,9 @@ _mm_cmpnle_sd(__m128d __a, __m128d __b) /// \brief Compares the lower double-precision floating-point values in each of /// the two 128-bit floating-point vectors of [2 x double] to determine if /// the value in the first parameter is not greater than the corresponding -/// value in the second parameter. The comparison yields 0h for false, -/// FFFFFFFFFFFFFFFFh for true. +/// value in the second parameter. +/// +/// The comparison yields 0h for false, FFFFFFFFFFFFFFFFh for true. /// /// \headerfile /// @@ -936,8 +959,9 @@ _mm_cmpngt_sd(__m128d __a, __m128d __b) /// \brief Compares the lower double-precision floating-point values in each of /// the two 128-bit floating-point vectors of [2 x double] to determine if /// the value in the first parameter is not greater than or equal to the -/// corresponding value in the second parameter. The comparison yields 0h -/// for false, FFFFFFFFFFFFFFFFh for true. +/// corresponding value in the second parameter. +/// +/// The comparison yields 0h for false, FFFFFFFFFFFFFFFFh for true. /// /// \headerfile /// @@ -982,7 +1006,9 @@ _mm_comieq_sd(__m128d __a, __m128d __b) /// \brief Compares the lower double-precision floating-point values in each of /// the two 128-bit floating-point vectors of [2 x double] to determine if /// the value in the first parameter is less than the corresponding value in -/// the second parameter. The comparison yields 0 for false, 1 for true. +/// the second parameter. +/// +/// The comparison yields 0 for false, 1 for true. /// /// \headerfile /// @@ -1004,8 +1030,9 @@ _mm_comilt_sd(__m128d __a, __m128d __b) /// \brief Compares the lower double-precision floating-point values in each of /// the two 128-bit floating-point vectors of [2 x double] to determine if /// the value in the first parameter is less than or equal to the -/// corresponding value in the second parameter. The comparison yields 0 for -/// false, 1 for true. +/// corresponding value in the second parameter. +/// +/// The comparison yields 0 for false, 1 for true. /// /// \headerfile /// @@ -1027,7 +1054,9 @@ _mm_comile_sd(__m128d __a, __m128d __b) /// \brief Compares the lower double-precision floating-point values in each of /// the two 128-bit floating-point vectors of [2 x double] to determine if /// the value in the first parameter is greater than the corresponding value -/// in the second parameter. The comparison yields 0 for false, 1 for true. +/// in the second parameter. +/// +/// The comparison yields 0 for false, 1 for true. /// /// \headerfile /// @@ -1049,8 +1078,9 @@ _mm_comigt_sd(__m128d __a, __m128d __b) /// \brief Compares the lower double-precision floating-point values in each of /// the two 128-bit floating-point vectors of [2 x double] to determine if /// the value in the first parameter is greater than or equal to the -/// corresponding value in the second parameter. The comparison yields 0 for -/// false, 1 for true. +/// corresponding value in the second parameter. +/// +/// The comparison yields 0 for false, 1 for true. /// /// \headerfile /// @@ -1072,7 +1102,9 @@ _mm_comige_sd(__m128d __a, __m128d __b) /// \brief Compares the lower double-precision floating-point values in each of /// the two 128-bit floating-point vectors of [2 x double] to determine if /// the value in the first parameter is unequal to the corresponding value in -/// the second parameter. The comparison yields 0 for false, 1 for true. +/// the second parameter. +/// +/// The comparison yields 0 for false, 1 for true. /// /// \headerfile /// @@ -1093,8 +1125,9 @@ _mm_comineq_sd(__m128d __a, __m128d __b) /// \brief Compares the lower double-precision floating-point values in each of /// the two 128-bit floating-point vectors of [2 x double] for equality. The -/// comparison yields 0 for false, 1 for true. If either of the two lower -/// double-precision values is NaN, 1 is returned. +/// comparison yields 0 for false, 1 for true. +/// +/// If either of the two lower double-precision values is NaN, 1 is returned. /// /// \headerfile /// @@ -1117,8 +1150,10 @@ _mm_ucomieq_sd(__m128d __a, __m128d __b) /// \brief Compares the lower double-precision floating-point values in each of /// the two 128-bit floating-point vectors of [2 x double] to determine if /// the value in the first parameter is less than the corresponding value in -/// the second parameter. The comparison yields 0 for false, 1 for true. If -/// either of the two lower double-precision values is NaN, 1 is returned. +/// the second parameter. +/// +/// The comparison yields 0 for false, 1 for true. If either of the two lower +/// double-precision values is NaN, 1 is returned. /// /// \headerfile /// @@ -1141,9 +1176,10 @@ _mm_ucomilt_sd(__m128d __a, __m128d __b) /// \brief Compares the lower double-precision floating-point values in each of /// the two 128-bit floating-point vectors of [2 x double] to determine if /// the value in the first parameter is less than or equal to the -/// corresponding value in the second parameter. The comparison yields 0 for -/// false, 1 for true. If either of the two lower double-precision values is -/// NaN, 1 is returned. +/// corresponding value in the second parameter. +/// +/// The comparison yields 0 for false, 1 for true. If either of the two lower +/// double-precision values is NaN, 1 is returned. /// /// \headerfile /// @@ -1166,8 +1202,10 @@ _mm_ucomile_sd(__m128d __a, __m128d __b) /// \brief Compares the lower double-precision floating-point values in each of /// the two 128-bit floating-point vectors of [2 x double] to determine if /// the value in the first parameter is greater than the corresponding value -/// in the second parameter. The comparison yields 0 for false, 1 for true. -/// If either of the two lower double-precision values is NaN, 0 is returned. +/// in the second parameter. +/// +/// The comparison yields 0 for false, 1 for true. If either of the two lower +/// double-precision values is NaN, 0 is returned. /// /// \headerfile /// @@ -1190,9 +1228,10 @@ _mm_ucomigt_sd(__m128d __a, __m128d __b) /// \brief Compares the lower double-precision floating-point values in each of /// the two 128-bit floating-point vectors of [2 x double] to determine if /// the value in the first parameter is greater than or equal to the -/// corresponding value in the second parameter. The comparison yields 0 for -/// false, 1 for true. If either of the two lower double-precision values -/// is NaN, 0 is returned. +/// corresponding value in the second parameter. +/// +/// The comparison yields 0 for false, 1 for true. If either of the two +/// lower double-precision values is NaN, 0 is returned. /// /// \headerfile /// @@ -1215,8 +1254,10 @@ _mm_ucomige_sd(__m128d __a, __m128d __b) /// \brief Compares the lower double-precision floating-point values in each of /// the two 128-bit floating-point vectors of [2 x double] to determine if /// the value in the first parameter is unequal to the corresponding value in -/// the second parameter. The comparison yields 0 for false, 1 for true. If -/// either of the two lower double-precision values is NaN, 0 is returned. +/// the second parameter. +/// +/// The comparison yields 0 for false, 1 for true. If either of the two lower +/// double-precision values is NaN, 0 is returned. /// /// \headerfile /// @@ -1278,8 +1319,9 @@ _mm_cvtps_pd(__m128 __a) /// \brief Converts the lower two integer elements of a 128-bit vector of /// [4 x i32] into two double-precision floating-point values, returned in a -/// 128-bit vector of [2 x double]. The upper two elements of the input -/// vector are unused. +/// 128-bit vector of [2 x double]. +/// +/// The upper two elements of the input vector are unused. /// /// \headerfile /// @@ -1287,7 +1329,9 @@ _mm_cvtps_pd(__m128 __a) /// /// \param __a /// A 128-bit integer vector of [4 x i32]. The lower two integer elements are -/// converted to double-precision values. The upper two elements are unused. +/// converted to double-precision values. +/// +/// The upper two elements are unused. /// \returns A 128-bit vector of [2 x double] containing the converted values. static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_cvtepi32_pd(__m128i __a) @@ -1409,10 +1453,11 @@ _mm_cvtss_sd(__m128d __a, __m128 __b) /// \brief Converts the two double-precision floating-point elements of a /// 128-bit vector of [2 x double] into two signed 32-bit integer values, -/// returned in the lower 64 bits of a 128-bit vector of [4 x i32]. If the -/// result of either conversion is inexact, the result is truncated (rounded -/// towards zero) regardless of the current MXCSR setting. The upper 64 bits -/// of the result vector are set to zero. +/// returned in the lower 64 bits of a 128-bit vector of [4 x i32]. +/// +/// If the result of either conversion is inexact, the result is truncated +/// (rounded towards zero) regardless of the current MXCSR setting. The upper +/// 64 bits of the result vector are set to zero. /// /// \headerfile /// @@ -1466,9 +1511,10 @@ _mm_cvtpd_pi32(__m128d __a) /// \brief Converts the two double-precision floating-point elements of a /// 128-bit vector of [2 x double] into two signed 32-bit integer values, -/// returned in a 64-bit vector of [2 x i32]. If the result of either -/// conversion is inexact, the result is truncated (rounded towards zero) -/// regardless of the current MXCSR setting. +/// returned in a 64-bit vector of [2 x i32]. +/// +/// If the result of either conversion is inexact, the result is truncated +/// (rounded towards zero) regardless of the current MXCSR setting. /// /// \headerfile /// @@ -1980,8 +2026,9 @@ _mm_storel_pd(double *__dp, __m128d __a) /// \brief Adds the corresponding elements of two 128-bit vectors of [16 x i8], /// saving the lower 8 bits of each sum in the corresponding element of a -/// 128-bit result vector of [16 x i8]. The integer elements of both -/// parameters can be either signed or unsigned. +/// 128-bit result vector of [16 x i8]. +/// +/// The integer elements of both parameters can be either signed or unsigned. /// /// \headerfile /// @@ -2001,8 +2048,9 @@ _mm_add_epi8(__m128i __a, __m128i __b) /// \brief Adds the corresponding elements of two 128-bit vectors of [8 x i16], /// saving the lower 16 bits of each sum in the corresponding element of a -/// 128-bit result vector of [8 x i16]. The integer elements of both -/// parameters can be either signed or unsigned. +/// 128-bit result vector of [8 x i16]. +/// +/// The integer elements of both parameters can be either signed or unsigned. /// /// \headerfile /// @@ -2022,8 +2070,9 @@ _mm_add_epi16(__m128i __a, __m128i __b) /// \brief Adds the corresponding elements of two 128-bit vectors of [4 x i32], /// saving the lower 32 bits of each sum in the corresponding element of a -/// 128-bit result vector of [4 x i32]. The integer elements of both -/// parameters can be either signed or unsigned. +/// 128-bit result vector of [4 x i32]. +/// +/// The integer elements of both parameters can be either signed or unsigned. /// /// \headerfile /// @@ -2061,8 +2110,9 @@ _mm_add_si64(__m64 __a, __m64 __b) /// \brief Adds the corresponding elements of two 128-bit vectors of [2 x i64], /// saving the lower 64 bits of each sum in the corresponding element of a -/// 128-bit result vector of [2 x i64]. The integer elements of both -/// parameters can be either signed or unsigned. +/// 128-bit result vector of [2 x i64]. +/// +/// The integer elements of both parameters can be either signed or unsigned. /// /// \headerfile /// @@ -2208,10 +2258,12 @@ _mm_avg_epu16(__m128i __a, __m128i __b) /// \brief Multiplies the corresponding elements of two 128-bit signed [8 x i16] /// vectors, producing eight intermediate 32-bit signed integer products, and /// adds the consecutive pairs of 32-bit products to form a 128-bit signed -/// [4 x i32] vector. For example, bits [15:0] of both parameters are -/// multiplied producing a 32-bit product, bits [31:16] of both parameters -/// are multiplied producing a 32-bit product, and the sum of those two -/// products becomes bits [31:0] of the result. +/// [4 x i32] vector. +/// +/// For example, bits [15:0] of both parameters are multiplied producing a +/// 32-bit product, bits [31:16] of both parameters are multiplied producing +/// a 32-bit product, and the sum of those two products becomes bits [31:0] +/// of the result. /// /// \headerfile /// @@ -3146,8 +3198,9 @@ _mm_cmpgt_epi8(__m128i __a, __m128i __b) /// \brief Compares each of the corresponding signed 16-bit values of the /// 128-bit integer vectors to determine if the values in the first operand -/// are greater than those in the second operand. Each comparison yields 0h -/// for false, FFFFh for true. +/// are greater than those in the second operand. +/// +/// Each comparison yields 0h for false, FFFFh for true. /// /// \headerfile /// @@ -3166,8 +3219,9 @@ _mm_cmpgt_epi16(__m128i __a, __m128i __b) /// \brief Compares each of the corresponding signed 32-bit values of the /// 128-bit integer vectors to determine if the values in the first operand -/// are greater than those in the second operand. Each comparison yields 0h -/// for false, FFFFFFFFh for true. +/// are greater than those in the second operand. +/// +/// Each comparison yields 0h for false, FFFFFFFFh for true. /// /// \headerfile /// @@ -3186,8 +3240,9 @@ _mm_cmpgt_epi32(__m128i __a, __m128i __b) /// \brief Compares each of the corresponding signed 8-bit values of the 128-bit /// integer vectors to determine if the values in the first operand are less -/// than those in the second operand. Each comparison yields 0h for false, -/// FFh for true. +/// than those in the second operand. +/// +/// Each comparison yields 0h for false, FFh for true. /// /// \headerfile /// @@ -3206,8 +3261,9 @@ _mm_cmplt_epi8(__m128i __a, __m128i __b) /// \brief Compares each of the corresponding signed 16-bit values of the /// 128-bit integer vectors to determine if the values in the first operand -/// are less than those in the second operand. Each comparison yields 0h for -/// false, FFFFh for true. +/// are less than those in the second operand. +/// +/// Each comparison yields 0h for false, FFFFh for true. /// /// \headerfile /// @@ -3226,8 +3282,9 @@ _mm_cmplt_epi16(__m128i __a, __m128i __b) /// \brief Compares each of the corresponding signed 32-bit values of the /// 128-bit integer vectors to determine if the values in the first operand -/// are less than those in the second operand. Each comparison yields 0h for -/// false, FFFFFFFFh for true. +/// are less than those in the second operand. +/// +/// Each comparison yields 0h for false, FFFFFFFFh for true. /// /// \headerfile /// @@ -3925,10 +3982,11 @@ _mm_storeu_si128(__m128i *__p, __m128i __b) /// \brief Moves bytes selected by the mask from the first operand to the /// specified unaligned memory location. When a mask bit is 1, the -/// corresponding byte is written, otherwise it is not written. To minimize -/// caching, the date is flagged as non-temporal (unlikely to be used again -/// soon). Exception and trap behavior for elements not selected for storage -/// to memory are implementation dependent. +/// corresponding byte is written, otherwise it is not written. +/// +/// To minimize caching, the date is flagged as non-temporal (unlikely to be +/// used again soon). Exception and trap behavior for elements not selected +/// for storage to memory are implementation dependent. /// /// \headerfile /// @@ -3972,8 +4030,10 @@ _mm_storel_epi64(__m128i *__p, __m128i __a) } /// \brief Stores a 128-bit floating point vector of [2 x double] to a 128-bit -/// aligned memory location. To minimize caching, the data is flagged as -/// non-temporal (unlikely to be used again soon). +/// aligned memory location. +/// +/// To minimize caching, the data is flagged as non-temporal (unlikely to be +/// used again soon). /// /// \headerfile /// @@ -3990,6 +4050,7 @@ _mm_stream_pd(double *__p, __m128d __a) } /// \brief Stores a 128-bit integer vector to a 128-bit aligned memory location. +/// /// To minimize caching, the data is flagged as non-temporal (unlikely to be /// used again soon). /// @@ -4007,8 +4068,9 @@ _mm_stream_si128(__m128i *__p, __m128i __a) __builtin_nontemporal_store((__v2di)__a, (__v2di*)__p); } -/// \brief Stores a 32-bit integer value in the specified memory location. To -/// minimize caching, the data is flagged as non-temporal (unlikely to be +/// \brief Stores a 32-bit integer value in the specified memory location. +/// +/// To minimize caching, the data is flagged as non-temporal (unlikely to be /// used again soon). /// /// \headerfile @@ -4026,8 +4088,9 @@ _mm_stream_si32(int *__p, int __a) } #ifdef __x86_64__ -/// \brief Stores a 64-bit integer value in the specified memory location. To -/// minimize caching, the data is flagged as non-temporal (unlikely to be +/// \brief Stores a 64-bit integer value in the specified memory location. +/// +/// To minimize caching, the data is flagged as non-temporal (unlikely to be /// used again soon). /// /// \headerfile diff --git a/lib/Headers/intrin.h b/lib/Headers/intrin.h index 38d9407abed9..881d05c0d164 100644 --- a/lib/Headers/intrin.h +++ b/lib/Headers/intrin.h @@ -85,9 +85,6 @@ void __inwordstring(unsigned short, unsigned short *, unsigned long); void __lidt(void *); unsigned __int64 __ll_lshift(unsigned __int64, int); __int64 __ll_rshift(__int64, int); -void __llwpcb(void *); -unsigned char __lwpins32(unsigned int, unsigned int, unsigned int); -void __lwpval32(unsigned int, unsigned int, unsigned int); unsigned int __lzcnt(unsigned int); unsigned short __lzcnt16(unsigned short); static __inline__ @@ -126,7 +123,6 @@ unsigned __int64 __readmsr(unsigned long); unsigned __int64 __readpmc(unsigned long); unsigned long __segmentlimit(unsigned long); void __sidt(void *); -void *__slwpcb(void); static __inline__ void __stosb(unsigned char *, unsigned char, size_t); static __inline__ @@ -227,8 +223,6 @@ void __incgsbyte(unsigned long); void __incgsdword(unsigned long); void __incgsqword(unsigned long); void __incgsword(unsigned long); -unsigned char __lwpins64(unsigned __int64, unsigned int, unsigned int); -void __lwpval64(unsigned __int64, unsigned int, unsigned int); unsigned __int64 __lzcnt64(unsigned __int64); static __inline__ void __movsq(unsigned long long *, unsigned long long const *, size_t); diff --git a/lib/Headers/mmintrin.h b/lib/Headers/mmintrin.h index 2b3618398cbf..5a7968bec842 100644 --- a/lib/Headers/mmintrin.h +++ b/lib/Headers/mmintrin.h @@ -608,10 +608,11 @@ _mm_subs_pi16(__m64 __m1, __m64 __m2) /// \brief Subtracts each 8-bit unsigned integer element of the second 64-bit /// integer vector of [8 x i8] from the corresponding 8-bit unsigned integer -/// element of the first 64-bit integer vector of [8 x i8]. If an element of -/// the first vector is less than the corresponding element of the second -/// vector, the result is saturated to 0. The results are packed into a -/// 64-bit integer vector of [8 x i8]. +/// element of the first 64-bit integer vector of [8 x i8]. +/// +/// If an element of the first vector is less than the corresponding element +/// of the second vector, the result is saturated to 0. The results are +/// packed into a 64-bit integer vector of [8 x i8]. /// /// \headerfile /// @@ -631,10 +632,11 @@ _mm_subs_pu8(__m64 __m1, __m64 __m2) /// \brief Subtracts each 16-bit unsigned integer element of the second 64-bit /// integer vector of [4 x i16] from the corresponding 16-bit unsigned -/// integer element of the first 64-bit integer vector of [4 x i16]. If an -/// element of the first vector is less than the corresponding element of the -/// second vector, the result is saturated to 0. The results are packed into -/// a 64-bit integer vector of [4 x i16]. +/// integer element of the first 64-bit integer vector of [4 x i16]. +/// +/// If an element of the first vector is less than the corresponding element +/// of the second vector, the result is saturated to 0. The results are +/// packed into a 64-bit integer vector of [4 x i16]. /// /// \headerfile /// @@ -657,9 +659,11 @@ _mm_subs_pu16(__m64 __m1, __m64 __m2) /// element of the second 64-bit integer vector of [4 x i16] and get four /// 32-bit products. Adds adjacent pairs of products to get two 32-bit sums. /// The lower 32 bits of these two sums are packed into a 64-bit integer -/// vector of [2 x i32]. For example, bits [15:0] of both parameters are -/// multiplied, bits [31:16] of both parameters are multiplied, and the sum -/// of both results is written to bits [31:0] of the result. +/// vector of [2 x i32]. +/// +/// For example, bits [15:0] of both parameters are multiplied, bits [31:16] +/// of both parameters are multiplied, and the sum of both results is written +/// to bits [31:0] of the result. /// /// \headerfile /// @@ -851,10 +855,11 @@ _mm_slli_si64(__m64 __m, int __count) /// \brief Right-shifts each 16-bit integer element of the first parameter, /// which is a 64-bit integer vector of [4 x i16], by the number of bits -/// specified by the second parameter, which is a 64-bit integer. High-order -/// bits are filled with the sign bit of the initial value of each 16-bit -/// element. The 16-bit results are packed into a 64-bit integer vector of -/// [4 x i16]. +/// specified by the second parameter, which is a 64-bit integer. +/// +/// High-order bits are filled with the sign bit of the initial value of each +/// 16-bit element. The 16-bit results are packed into a 64-bit integer +/// vector of [4 x i16]. /// /// \headerfile /// @@ -874,6 +879,7 @@ _mm_sra_pi16(__m64 __m, __m64 __count) /// \brief Right-shifts each 16-bit integer element of a 64-bit integer vector /// of [4 x i16] by the number of bits specified by a 32-bit integer. +/// /// High-order bits are filled with the sign bit of the initial value of each /// 16-bit element. The 16-bit results are packed into a 64-bit integer /// vector of [4 x i16]. @@ -896,10 +902,11 @@ _mm_srai_pi16(__m64 __m, int __count) /// \brief Right-shifts each 32-bit integer element of the first parameter, /// which is a 64-bit integer vector of [2 x i32], by the number of bits -/// specified by the second parameter, which is a 64-bit integer. High-order -/// bits are filled with the sign bit of the initial value of each 32-bit -/// element. The 32-bit results are packed into a 64-bit integer vector of -/// [2 x i32]. +/// specified by the second parameter, which is a 64-bit integer. +/// +/// High-order bits are filled with the sign bit of the initial value of each +/// 32-bit element. The 32-bit results are packed into a 64-bit integer +/// vector of [2 x i32]. /// /// \headerfile /// @@ -919,6 +926,7 @@ _mm_sra_pi32(__m64 __m, __m64 __count) /// \brief Right-shifts each 32-bit integer element of a 64-bit integer vector /// of [2 x i32] by the number of bits specified by a 32-bit integer. +/// /// High-order bits are filled with the sign bit of the initial value of each /// 32-bit element. The 32-bit results are packed into a 64-bit integer /// vector of [2 x i32]. @@ -941,9 +949,10 @@ _mm_srai_pi32(__m64 __m, int __count) /// \brief Right-shifts each 16-bit integer element of the first parameter, /// which is a 64-bit integer vector of [4 x i16], by the number of bits -/// specified by the second parameter, which is a 64-bit integer. High-order -/// bits are cleared. The 16-bit results are packed into a 64-bit integer -/// vector of [4 x i16]. +/// specified by the second parameter, which is a 64-bit integer. +/// +/// High-order bits are cleared. The 16-bit results are packed into a 64-bit +/// integer vector of [4 x i16]. /// /// \headerfile /// @@ -963,6 +972,7 @@ _mm_srl_pi16(__m64 __m, __m64 __count) /// \brief Right-shifts each 16-bit integer element of a 64-bit integer vector /// of [4 x i16] by the number of bits specified by a 32-bit integer. +/// /// High-order bits are cleared. The 16-bit results are packed into a 64-bit /// integer vector of [4 x i16]. /// @@ -984,9 +994,10 @@ _mm_srli_pi16(__m64 __m, int __count) /// \brief Right-shifts each 32-bit integer element of the first parameter, /// which is a 64-bit integer vector of [2 x i32], by the number of bits -/// specified by the second parameter, which is a 64-bit integer. High-order -/// bits are cleared. The 32-bit results are packed into a 64-bit integer -/// vector of [2 x i32]. +/// specified by the second parameter, which is a 64-bit integer. +/// +/// High-order bits are cleared. The 32-bit results are packed into a 64-bit +/// integer vector of [2 x i32]. /// /// \headerfile /// @@ -1006,6 +1017,7 @@ _mm_srl_pi32(__m64 __m, __m64 __count) /// \brief Right-shifts each 32-bit integer element of a 64-bit integer vector /// of [2 x i32] by the number of bits specified by a 32-bit integer. +/// /// High-order bits are cleared. The 32-bit results are packed into a 64-bit /// integer vector of [2 x i32]. /// @@ -1026,8 +1038,9 @@ _mm_srli_pi32(__m64 __m, int __count) } /// \brief Right-shifts the first 64-bit integer parameter by the number of bits -/// specified by the second 64-bit integer parameter. High-order bits are -/// cleared. +/// specified by the second 64-bit integer parameter. +/// +/// High-order bits are cleared. /// /// \headerfile /// @@ -1046,7 +1059,9 @@ _mm_srl_si64(__m64 __m, __m64 __count) /// \brief Right-shifts the first parameter, which is a 64-bit integer, by the /// number of bits specified by the second parameter, which is a 32-bit -/// integer. High-order bits are cleared. +/// integer. +/// +/// High-order bits are cleared. /// /// \headerfile /// @@ -1140,8 +1155,9 @@ _mm_xor_si64(__m64 __m1, __m64 __m2) /// \brief Compares the 8-bit integer elements of two 64-bit integer vectors of /// [8 x i8] to determine if the element of the first vector is equal to the -/// corresponding element of the second vector. The comparison yields 0 for -/// false, 0xFF for true. +/// corresponding element of the second vector. +/// +/// The comparison yields 0 for false, 0xFF for true. /// /// \headerfile /// @@ -1161,8 +1177,9 @@ _mm_cmpeq_pi8(__m64 __m1, __m64 __m2) /// \brief Compares the 16-bit integer elements of two 64-bit integer vectors of /// [4 x i16] to determine if the element of the first vector is equal to the -/// corresponding element of the second vector. The comparison yields 0 for -/// false, 0xFFFF for true. +/// corresponding element of the second vector. +/// +/// The comparison yields 0 for false, 0xFFFF for true. /// /// \headerfile /// @@ -1182,8 +1199,9 @@ _mm_cmpeq_pi16(__m64 __m1, __m64 __m2) /// \brief Compares the 32-bit integer elements of two 64-bit integer vectors of /// [2 x i32] to determine if the element of the first vector is equal to the -/// corresponding element of the second vector. The comparison yields 0 for -/// false, 0xFFFFFFFF for true. +/// corresponding element of the second vector. +/// +/// The comparison yields 0 for false, 0xFFFFFFFF for true. /// /// \headerfile /// @@ -1203,8 +1221,9 @@ _mm_cmpeq_pi32(__m64 __m1, __m64 __m2) /// \brief Compares the 8-bit integer elements of two 64-bit integer vectors of /// [8 x i8] to determine if the element of the first vector is greater than -/// the corresponding element of the second vector. The comparison yields 0 -/// for false, 0xFF for true. +/// the corresponding element of the second vector. +/// +/// The comparison yields 0 for false, 0xFF for true. /// /// \headerfile /// @@ -1224,8 +1243,9 @@ _mm_cmpgt_pi8(__m64 __m1, __m64 __m2) /// \brief Compares the 16-bit integer elements of two 64-bit integer vectors of /// [4 x i16] to determine if the element of the first vector is greater than -/// the corresponding element of the second vector. The comparison yields 0 -/// for false, 0xFFFF for true. +/// the corresponding element of the second vector. +/// +/// The comparison yields 0 for false, 0xFFFF for true. /// /// \headerfile /// @@ -1245,8 +1265,9 @@ _mm_cmpgt_pi16(__m64 __m1, __m64 __m2) /// \brief Compares the 32-bit integer elements of two 64-bit integer vectors of /// [2 x i32] to determine if the element of the first vector is greater than -/// the corresponding element of the second vector. The comparison yields 0 -/// for false, 0xFFFFFFFF for true. +/// the corresponding element of the second vector. +/// +/// The comparison yields 0 for false, 0xFFFFFFFF for true. /// /// \headerfile /// diff --git a/lib/Headers/opencl-c.h b/lib/Headers/opencl-c.h index 6452d5c987f0..58c8daf3a536 100644 --- a/lib/Headers/opencl-c.h +++ b/lib/Headers/opencl-c.h @@ -14962,6 +14962,7 @@ float __purefn __ovld read_imagef(read_only image2d_array_msaa_depth_t image, in #endif //cl_khr_gl_msaa_sharing // OpenCL Extension v2.0 s9.18 - Mipmaps +#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 #ifdef cl_khr_mipmap_image float4 __purefn __ovld read_imagef(read_only image1d_t image, sampler_t sampler, float coord, float lod); @@ -15037,6 +15038,7 @@ int4 __purefn __ovld read_imagei(read_only image3d_t image, sampler_t sampler, f uint4 __purefn __ovld read_imageui(read_only image3d_t image, sampler_t sampler, float4 coord, float lod); #endif //cl_khr_mipmap_image +#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 /** * Sampler-less Image Access @@ -15135,6 +15137,7 @@ float __purefn __ovld read_imagef(read_write image2d_msaa_depth_t image, int2 co float __purefn __ovld read_imagef(read_write image2d_array_msaa_depth_t image, int4 coord, int sample); #endif //cl_khr_gl_msaa_sharing +#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 #ifdef cl_khr_mipmap_image float4 __purefn __ovld read_imagef(read_write image1d_t image, sampler_t sampler, float coord, float lod); int4 __purefn __ovld read_imagei(read_write image1d_t image, sampler_t sampler, float coord, float lod); @@ -15208,6 +15211,7 @@ float4 __purefn __ovld read_imagef(read_write image3d_t image, sampler_t sampler int4 __purefn __ovld read_imagei(read_write image3d_t image, sampler_t sampler, float4 coord, float lod); uint4 __purefn __ovld read_imageui(read_write image3d_t image, sampler_t sampler, float4 coord, float lod); #endif //cl_khr_mipmap_image +#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 // Image read functions returning half4 type #ifdef cl_khr_fp16 @@ -15319,6 +15323,7 @@ void __ovld write_imagef(write_only image2d_array_depth_t image, int4 coord, flo #endif //cl_khr_depth_images // OpenCL Extension v2.0 s9.18 - Mipmaps +#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 #ifdef cl_khr_mipmap_image void __ovld write_imagef(write_only image1d_t image, int coord, int lod, float4 color); void __ovld write_imagei(write_only image1d_t image, int coord, int lod, int4 color); @@ -15345,6 +15350,7 @@ void __ovld write_imagei(write_only image3d_t image, int4 coord, int lod, int4 c void __ovld write_imageui(write_only image3d_t image, int4 coord, int lod, uint4 color); #endif #endif //cl_khr_mipmap_image +#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 // Image write functions for half4 type #ifdef cl_khr_fp16 @@ -15391,6 +15397,7 @@ void __ovld write_imagef(read_write image2d_depth_t image, int2 coord, float col void __ovld write_imagef(read_write image2d_array_depth_t image, int4 coord, float color); #endif //cl_khr_depth_images +#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 #ifdef cl_khr_mipmap_image void __ovld write_imagef(read_write image1d_t image, int coord, int lod, float4 color); void __ovld write_imagei(read_write image1d_t image, int coord, int lod, int4 color); @@ -15417,6 +15424,7 @@ void __ovld write_imagei(read_write image3d_t image, int4 coord, int lod, int4 c void __ovld write_imageui(read_write image3d_t image, int4 coord, int lod, uint4 color); #endif #endif //cl_khr_mipmap_image +#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 // Image write functions for half4 type #ifdef cl_khr_fp16 @@ -15559,6 +15567,7 @@ int __ovld __cnfn get_image_depth(read_write image3d_t image); #endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 // OpenCL Extension v2.0 s9.18 - Mipmaps +#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 #ifdef cl_khr_mipmap_image /** * Return the image miplevels. @@ -15574,11 +15583,9 @@ int __ovld get_image_num_mip_levels(write_only image2d_t image); int __ovld get_image_num_mip_levels(write_only image3d_t image); #endif -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 int __ovld get_image_num_mip_levels(read_write image1d_t image); int __ovld get_image_num_mip_levels(read_write image2d_t image); int __ovld get_image_num_mip_levels(read_write image3d_t image); -#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 int __ovld get_image_num_mip_levels(read_only image1d_array_t image); int __ovld get_image_num_mip_levels(read_only image2d_array_t image); @@ -15590,14 +15597,13 @@ int __ovld get_image_num_mip_levels(write_only image2d_array_t image); int __ovld get_image_num_mip_levels(write_only image2d_array_depth_t image); int __ovld get_image_num_mip_levels(write_only image2d_depth_t image); -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 int __ovld get_image_num_mip_levels(read_write image1d_array_t image); int __ovld get_image_num_mip_levels(read_write image2d_array_t image); int __ovld get_image_num_mip_levels(read_write image2d_array_depth_t image); int __ovld get_image_num_mip_levels(read_write image2d_depth_t image); -#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 #endif //cl_khr_mipmap_image +#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 /** * Return the channel data type. Valid values are: diff --git a/lib/Headers/pmmintrin.h b/lib/Headers/pmmintrin.h index a479d9ed2911..559ece2e3974 100644 --- a/lib/Headers/pmmintrin.h +++ b/lib/Headers/pmmintrin.h @@ -31,9 +31,11 @@ __attribute__((__always_inline__, __nodebug__, __target__("sse3"))) /// \brief Loads data from an unaligned memory location to elements in a 128-bit -/// vector. If the address of the data is not 16-byte aligned, the -/// instruction may read two adjacent aligned blocks of memory to retrieve -/// the requested data. +/// vector. +/// +/// If the address of the data is not 16-byte aligned, the instruction may +/// read two adjacent aligned blocks of memory to retrieve the requested +/// data. /// /// \headerfile /// diff --git a/lib/Headers/prfchwintrin.h b/lib/Headers/prfchwintrin.h index a3789126ef07..b52f31da2706 100644 --- a/lib/Headers/prfchwintrin.h +++ b/lib/Headers/prfchwintrin.h @@ -50,8 +50,10 @@ _m_prefetch(void *__P) /// the L1 data cache and sets the cache-coherency to modified. This /// provides a hint to the processor that the cache line will be modified. /// It is intended for use when the cache line will be written to shortly -/// after the prefetch is performed. Note that the effect of this intrinsic -/// is dependent on the processor implementation. +/// after the prefetch is performed. +/// +/// Note that the effect of this intrinsic is dependent on the processor +/// implementation. /// /// \headerfile /// diff --git a/lib/Headers/smmintrin.h b/lib/Headers/smmintrin.h index 1c94aca69381..c2fa5a452bce 100644 --- a/lib/Headers/smmintrin.h +++ b/lib/Headers/smmintrin.h @@ -586,7 +586,9 @@ _mm_mul_epi32 (__m128i __V1, __m128i __V2) /* SSE4 Floating Point Dot Product Instructions. */ /// \brief Computes the dot product of the two 128-bit vectors of [4 x float] /// and returns it in the elements of the 128-bit result vector of -/// [4 x float]. The immediate integer operand controls which input elements +/// [4 x float]. +/// +/// The immediate integer operand controls which input elements /// will contribute to the dot product, and where the final results are /// returned. /// @@ -620,7 +622,9 @@ _mm_mul_epi32 (__m128i __V1, __m128i __V2) /// \brief Computes the dot product of the two 128-bit vectors of [2 x double] /// and returns it in the elements of the 128-bit result vector of -/// [2 x double]. The immediate integer operand controls which input +/// [2 x double]. +/// +/// The immediate integer operand controls which input /// elements will contribute to the dot product, and where the final results /// are returned. /// @@ -875,7 +879,7 @@ _mm_max_epu32 (__m128i __V1, __m128i __V2) /// int _mm_extract_ps(__m128 X, const int N); /// \endcode /// -/// This intrinsic corresponds to the VEXTRACTPS / EXTRACTPS +/// This intrinsic corresponds to the VEXTRACTPS / EXTRACTPS /// instruction. /// /// \param X diff --git a/lib/Headers/tmmintrin.h b/lib/Headers/tmmintrin.h index 80664043a06f..042bfc7e3b0d 100644 --- a/lib/Headers/tmmintrin.h +++ b/lib/Headers/tmmintrin.h @@ -469,10 +469,11 @@ _mm_hsubs_pi16(__m64 __a, __m64 __b) /// values contained in the first source operand and packed 8-bit signed /// integer values contained in the second source operand, adds pairs of /// contiguous products with signed saturation, and writes the 16-bit sums to -/// the corresponding bits in the destination. For example, bits [7:0] of -/// both operands are multiplied, bits [15:8] of both operands are -/// multiplied, and the sum of both results is written to bits [15:0] of the -/// destination. +/// the corresponding bits in the destination. +/// +/// For example, bits [7:0] of both operands are multiplied, bits [15:8] of +/// both operands are multiplied, and the sum of both results is written to +/// bits [15:0] of the destination. /// /// \headerfile /// @@ -502,10 +503,11 @@ _mm_maddubs_epi16(__m128i __a, __m128i __b) /// values contained in the first source operand and packed 8-bit signed /// integer values contained in the second source operand, adds pairs of /// contiguous products with signed saturation, and writes the 16-bit sums to -/// the corresponding bits in the destination. For example, bits [7:0] of -/// both operands are multiplied, bits [15:8] of both operands are -/// multiplied, and the sum of both results is written to bits [15:0] of the -/// destination. +/// the corresponding bits in the destination. +/// +/// For example, bits [7:0] of both operands are multiplied, bits [15:8] of +/// both operands are multiplied, and the sum of both results is written to +/// bits [15:0] of the destination. /// /// \headerfile /// @@ -619,13 +621,14 @@ _mm_shuffle_pi8(__m64 __a, __m64 __b) } /// \brief For each 8-bit integer in the first source operand, perform one of -/// the following actions as specified by the second source operand: If the -/// byte in the second source is negative, calculate the two's complement of -/// the corresponding byte in the first source, and write that value to the -/// destination. If the byte in the second source is positive, copy the -/// corresponding byte from the first source to the destination. If the byte -/// in the second source is zero, clear the corresponding byte in the -/// destination. +/// the following actions as specified by the second source operand. +/// +/// If the byte in the second source is negative, calculate the two's +/// complement of the corresponding byte in the first source, and write that +/// value to the destination. If the byte in the second source is positive, +/// copy the corresponding byte from the first source to the destination. If +/// the byte in the second source is zero, clear the corresponding byte in +/// the destination. /// /// \headerfile /// @@ -644,13 +647,14 @@ _mm_sign_epi8(__m128i __a, __m128i __b) } /// \brief For each 16-bit integer in the first source operand, perform one of -/// the following actions as specified by the second source operand: If the -/// word in the second source is negative, calculate the two's complement of -/// the corresponding word in the first source, and write that value to the -/// destination. If the word in the second source is positive, copy the -/// corresponding word from the first source to the destination. If the word -/// in the second source is zero, clear the corresponding word in the -/// destination. +/// the following actions as specified by the second source operand. +/// +/// If the word in the second source is negative, calculate the two's +/// complement of the corresponding word in the first source, and write that +/// value to the destination. If the word in the second source is positive, +/// copy the corresponding word from the first source to the destination. If +/// the word in the second source is zero, clear the corresponding word in +/// the destination. /// /// \headerfile /// @@ -669,8 +673,9 @@ _mm_sign_epi16(__m128i __a, __m128i __b) } /// \brief For each 32-bit integer in the first source operand, perform one of -/// the following actions as specified by the second source operand: If the -/// doubleword in the second source is negative, calculate the two's +/// the following actions as specified by the second source operand. +/// +/// If the doubleword in the second source is negative, calculate the two's /// complement of the corresponding word in the first source, and write that /// value to the destination. If the doubleword in the second source is /// positive, copy the corresponding word from the first source to the @@ -694,13 +699,14 @@ _mm_sign_epi32(__m128i __a, __m128i __b) } /// \brief For each 8-bit integer in the first source operand, perform one of -/// the following actions as specified by the second source operand: If the -/// byte in the second source is negative, calculate the two's complement of -/// the corresponding byte in the first source, and write that value to the -/// destination. If the byte in the second source is positive, copy the -/// corresponding byte from the first source to the destination. If the byte -/// in the second source is zero, clear the corresponding byte in the -/// destination. +/// the following actions as specified by the second source operand. +/// +/// If the byte in the second source is negative, calculate the two's +/// complement of the corresponding byte in the first source, and write that +/// value to the destination. If the byte in the second source is positive, +/// copy the corresponding byte from the first source to the destination. If +/// the byte in the second source is zero, clear the corresponding byte in +/// the destination. /// /// \headerfile /// @@ -719,13 +725,14 @@ _mm_sign_pi8(__m64 __a, __m64 __b) } /// \brief For each 16-bit integer in the first source operand, perform one of -/// the following actions as specified by the second source operand: If the -/// word in the second source is negative, calculate the two's complement of -/// the corresponding word in the first source, and write that value to the -/// destination. If the word in the second source is positive, copy the -/// corresponding word from the first source to the destination. If the word -/// in the second source is zero, clear the corresponding word in the -/// destination. +/// the following actions as specified by the second source operand. +/// +/// If the word in the second source is negative, calculate the two's +/// complement of the corresponding word in the first source, and write that +/// value to the destination. If the word in the second source is positive, +/// copy the corresponding word from the first source to the destination. If +/// the word in the second source is zero, clear the corresponding word in +/// the destination. /// /// \headerfile /// @@ -744,8 +751,9 @@ _mm_sign_pi16(__m64 __a, __m64 __b) } /// \brief For each 32-bit integer in the first source operand, perform one of -/// the following actions as specified by the second source operand: If the -/// doubleword in the second source is negative, calculate the two's +/// the following actions as specified by the second source operand. +/// +/// If the doubleword in the second source is negative, calculate the two's /// complement of the corresponding doubleword in the first source, and /// write that value to the destination. If the doubleword in the second /// source is positive, copy the corresponding doubleword from the first diff --git a/lib/Headers/x86intrin.h b/lib/Headers/x86intrin.h index ef1d02948c8b..31ee7b82dd53 100644 --- a/lib/Headers/x86intrin.h +++ b/lib/Headers/x86intrin.h @@ -88,6 +88,4 @@ #include #endif -/* FIXME: LWP */ - #endif /* __X86INTRIN_H */ diff --git a/lib/Headers/xmmintrin.h b/lib/Headers/xmmintrin.h index 5c312c08efb6..9773acb840a5 100644 --- a/lib/Headers/xmmintrin.h +++ b/lib/Headers/xmmintrin.h @@ -2331,8 +2331,10 @@ _mm_mulhi_pu16(__m64 __a, __m64 __b) /// \brief Conditionally copies the values from each 8-bit element in the first /// 64-bit integer vector operand to the specified memory location, as /// specified by the most significant bit in the corresponding element in the -/// second 64-bit integer vector operand. To minimize caching, the data is -/// flagged as non-temporal (unlikely to be used again soon). +/// second 64-bit integer vector operand. +/// +/// To minimize caching, the data is flagged as non-temporal +/// (unlikely to be used again soon). /// /// \headerfile /// @@ -2815,11 +2817,12 @@ _mm_cvtpi32x2_ps(__m64 __a, __m64 __b) /// \brief Converts each single-precision floating-point element of a 128-bit /// floating-point vector of [4 x float] into a 16-bit signed integer, and -/// packs the results into a 64-bit integer vector of [4 x i16]. If the -/// floating-point element is NaN or infinity, or if the floating-point -/// element is greater than 0x7FFFFFFF or less than -0x8000, it is converted -/// to 0x8000. Otherwise if the floating-point element is greater than -/// 0x7FFF, it is converted to 0x7FFF. +/// packs the results into a 64-bit integer vector of [4 x i16]. +/// +/// If the floating-point element is NaN or infinity, or if the +/// floating-point element is greater than 0x7FFFFFFF or less than -0x8000, +/// it is converted to 0x8000. Otherwise if the floating-point element is +/// greater than 0x7FFF, it is converted to 0x7FFF. /// /// \headerfile /// @@ -2845,11 +2848,12 @@ _mm_cvtps_pi16(__m128 __a) /// \brief Converts each single-precision floating-point element of a 128-bit /// floating-point vector of [4 x float] into an 8-bit signed integer, and /// packs the results into the lower 32 bits of a 64-bit integer vector of -/// [8 x i8]. The upper 32 bits of the vector are set to 0. If the -/// floating-point element is NaN or infinity, or if the floating-point -/// element is greater than 0x7FFFFFFF or less than -0x80, it is converted -/// to 0x80. Otherwise if the floating-point element is greater than 0x7F, -/// it is converted to 0x7F. +/// [8 x i8]. The upper 32 bits of the vector are set to 0. +/// +/// If the floating-point element is NaN or infinity, or if the +/// floating-point element is greater than 0x7FFFFFFF or less than -0x80, it +/// is converted to 0x80. Otherwise if the floating-point element is greater +/// than 0x7F, it is converted to 0x7F. /// /// \headerfile /// diff --git a/lib/Index/IndexBody.cpp b/lib/Index/IndexBody.cpp index 7f09290de40f..08d233fb83e0 100644 --- a/lib/Index/IndexBody.cpp +++ b/lib/Index/IndexBody.cpp @@ -150,6 +150,53 @@ class BodyIndexer : public RecursiveASTVisitor { Parent, ParentDC, Roles, Relations, E); } + bool indexDependentReference( + const Expr *E, const Type *T, const DeclarationNameInfo &NameInfo, + llvm::function_ref Filter) { + if (!T) + return true; + const TemplateSpecializationType *TST = + T->getAs(); + if (!TST) + return true; + TemplateName TN = TST->getTemplateName(); + const ClassTemplateDecl *TD = + dyn_cast_or_null(TN.getAsTemplateDecl()); + if (!TD) + return true; + CXXRecordDecl *RD = TD->getTemplatedDecl(); + if (!RD->hasDefinition()) + return true; + RD = RD->getDefinition(); + std::vector Symbols = + RD->lookupDependentName(NameInfo.getName(), Filter); + // FIXME: Improve overload handling. + if (Symbols.size() != 1) + return true; + SourceLocation Loc = NameInfo.getLoc(); + if (Loc.isInvalid()) + Loc = E->getLocStart(); + SmallVector Relations; + SymbolRoleSet Roles = getRolesForRef(E, Relations); + return IndexCtx.handleReference(Symbols[0], Loc, Parent, ParentDC, Roles, + Relations, E); + } + + bool VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) { + const DeclarationNameInfo &Info = E->getMemberNameInfo(); + return indexDependentReference( + E, E->getBaseType().getTypePtrOrNull(), Info, + [](const NamedDecl *D) { return D->isCXXInstanceMember(); }); + } + + bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) { + const DeclarationNameInfo &Info = E->getNameInfo(); + const NestedNameSpecifier *NNS = E->getQualifier(); + return indexDependentReference( + E, NNS->getAsType(), Info, + [](const NamedDecl *D) { return !D->isCXXInstanceMember(); }); + } + bool VisitDesignatedInitExpr(DesignatedInitExpr *E) { for (DesignatedInitExpr::Designator &D : llvm::reverse(E->designators())) { if (D.isFieldDesignator() && D.getField()) diff --git a/lib/Index/IndexDecl.cpp b/lib/Index/IndexDecl.cpp index 7de70a10b692..203862c46e98 100644 --- a/lib/Index/IndexDecl.cpp +++ b/lib/Index/IndexDecl.cpp @@ -52,6 +52,22 @@ class IndexingDeclVisitor : public ConstDeclVisitor { return MD && !MD->isImplicit() && MD->isThisDeclarationADefinition(); } + void handleTemplateArgumentLoc(const TemplateArgumentLoc &TALoc, + const NamedDecl *Parent, + const DeclContext *DC) { + const TemplateArgumentLocInfo &LocInfo = TALoc.getLocInfo(); + switch (TALoc.getArgument().getKind()) { + case TemplateArgument::Expression: + IndexCtx.indexBody(LocInfo.getAsExpr(), Parent, DC); + break; + case TemplateArgument::Type: + IndexCtx.indexTypeSourceInfo(LocInfo.getAsTypeSourceInfo(), Parent, DC); + break; + default: + break; + } + } + void handleDeclarator(const DeclaratorDecl *D, const NamedDecl *Parent = nullptr, bool isIBType = false) { @@ -233,6 +249,12 @@ class IndexingDeclVisitor : public ConstDeclVisitor { Dtor->getParent(), Dtor->getDeclContext()); } } + // Template specialization arguments. + if (const ASTTemplateArgumentListInfo *TemplateArgInfo = + D->getTemplateSpecializationArgsAsWritten()) { + for (const auto &Arg : TemplateArgInfo->arguments()) + handleTemplateArgumentLoc(Arg, D, D->getLexicalDeclContext()); + } if (D->isThisDeclarationADefinition()) { const Stmt *Body = D->getBody(); @@ -522,6 +544,14 @@ class IndexingDeclVisitor : public ConstDeclVisitor { return true; } + bool VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) { + TRY_DECL(D, IndexCtx.handleDecl(D)); + IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D); + IndexCtx.handleReference(D->getAliasedNamespace(), D->getTargetNameLoc(), D, + D->getLexicalDeclContext()); + return true; + } + bool VisitUsingDecl(const UsingDecl *D) { const DeclContext *DC = D->getDeclContext()->getRedeclContext(); const NamedDecl *Parent = dyn_cast(DC); diff --git a/lib/Index/IndexTypeSourceInfo.cpp b/lib/Index/IndexTypeSourceInfo.cpp index 44d1241fb930..ae27ebe6ea4c 100644 --- a/lib/Index/IndexTypeSourceInfo.cpp +++ b/lib/Index/IndexTypeSourceInfo.cpp @@ -141,6 +141,34 @@ class TypeIndexer : public RecursiveASTVisitor { return true; } + bool VisitDependentNameTypeLoc(DependentNameTypeLoc TL) { + const DependentNameType *DNT = TL.getTypePtr(); + const NestedNameSpecifier *NNS = DNT->getQualifier(); + const Type *T = NNS->getAsType(); + if (!T) + return true; + const TemplateSpecializationType *TST = + T->getAs(); + if (!TST) + return true; + TemplateName TN = TST->getTemplateName(); + const ClassTemplateDecl *TD = + dyn_cast_or_null(TN.getAsTemplateDecl()); + if (!TD) + return true; + CXXRecordDecl *RD = TD->getTemplatedDecl(); + if (!RD->hasDefinition()) + return true; + RD = RD->getDefinition(); + DeclarationName Name(DNT->getIdentifier()); + std::vector Symbols = RD->lookupDependentName( + Name, [](const NamedDecl *ND) { return isa(ND); }); + if (Symbols.size() != 1) + return true; + return IndexCtx.handleReference(Symbols[0], TL.getNameLoc(), Parent, + ParentDC, SymbolRoleSet(), Relations); + } + bool TraverseStmt(Stmt *S) { IndexCtx.indexBody(S, Parent, ParentDC); return true; @@ -184,7 +212,7 @@ void IndexingContext::indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, if (!DC) DC = Parent->getLexicalDeclContext(); - SourceLocation Loc = NNS.getSourceRange().getBegin(); + SourceLocation Loc = NNS.getLocalBeginLoc(); switch (NNS.getNestedNameSpecifier()->getKind()) { case NestedNameSpecifier::Identifier: diff --git a/lib/Index/IndexingContext.cpp b/lib/Index/IndexingContext.cpp index 709a23657b07..5cebb198460f 100644 --- a/lib/Index/IndexingContext.cpp +++ b/lib/Index/IndexingContext.cpp @@ -124,6 +124,10 @@ bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) { TKind = FD->getTemplateSpecializationKind(); } else if (auto *VD = dyn_cast(D)) { TKind = VD->getTemplateSpecializationKind(); + } else if (isa(D)) { + if (const auto *Parent = + dyn_cast(D->getDeclContext())) + TKind = Parent->getSpecializationKind(); } switch (TKind) { case TSK_Undeclared: @@ -159,6 +163,17 @@ static const Decl *adjustTemplateImplicitInstantiation(const Decl *D) { return FD->getTemplateInstantiationPattern(); } else if (auto *VD = dyn_cast(D)) { return VD->getTemplateInstantiationPattern(); + } else if (const auto *FD = dyn_cast(D)) { + if (const auto *Parent = + dyn_cast(D->getDeclContext())) { + const CXXRecordDecl *Pattern = Parent->getTemplateInstantiationPattern(); + for (const NamedDecl *ND : Pattern->lookup(FD->getDeclName())) { + if (ND->isImplicit()) + continue; + if (isa(ND)) + return ND; + } + } } return nullptr; } diff --git a/lib/Lex/MacroInfo.cpp b/lib/Lex/MacroInfo.cpp index bec434085e3a..1e5deeb1919b 100644 --- a/lib/Lex/MacroInfo.cpp +++ b/lib/Lex/MacroInfo.cpp @@ -29,7 +29,6 @@ MacroInfo::MacroInfo(SourceLocation DefLoc) IsUsed(false), IsAllowRedefinitionsWithoutWarning(false), IsWarnIfUnused(false), - FromASTFile(false), UsedForHeaderGuard(false) { } @@ -137,7 +136,6 @@ LLVM_DUMP_METHOD void MacroInfo::dump() const { if (IsAllowRedefinitionsWithoutWarning) Out << " allow_redefinitions_without_warning"; if (IsWarnIfUnused) Out << " warn_if_unused"; - if (FromASTFile) Out << " imported"; if (UsedForHeaderGuard) Out << " header_guard"; Out << "\n #define "; diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp index 70d37d3d7082..6f44dc757e85 100644 --- a/lib/Lex/ModuleMap.cpp +++ b/lib/Lex/ModuleMap.cpp @@ -1485,7 +1485,19 @@ void ModuleMapParser::parseModuleDecl() { // Determine whether this (sub)module has already been defined. if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) { - if (Existing->DefinitionLoc.isInvalid() && !ActiveModule) { + // We might see a (re)definition of a module that we already have a + // definition for in two cases: + // - If we loaded one definition from an AST file and we've just found a + // corresponding definition in a module map file, or + bool LoadedFromASTFile = Existing->DefinitionLoc.isInvalid(); + // - If we're building a (preprocessed) module and we've just loaded the + // module map file from which it was created. + bool ParsedAsMainInput = + Map.LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap && + Map.LangOpts.CurrentModule == ModuleName && + SourceMgr.getDecomposedLoc(ModuleNameLoc).first != + SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first; + if (!ActiveModule && (LoadedFromASTFile || ParsedAsMainInput)) { // Skip the module definition. skipUntil(MMToken::RBrace); if (Tok.is(MMToken::RBrace)) @@ -1901,8 +1913,10 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken, // 'framework module FrameworkName.Private', since a 'Private.Framework' // does not usually exist. However, since both are currently widely used // for private modules, make sure we find the right path in both cases. - RelativePathName.resize(ActiveModule->IsFramework ? 0 - : RelativePathLength); + if (ActiveModule->IsFramework && ActiveModule->Name == "Private") + RelativePathName.clear(); + else + RelativePathName.resize(RelativePathLength); FullPathName.resize(FullPathLength); llvm::sys::path::append(RelativePathName, "PrivateHeaders", Header.FileName); diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp index 06fee8e5b0a8..faf8809e4eb4 100644 --- a/lib/Lex/PPDirectives.cpp +++ b/lib/Lex/PPDirectives.cpp @@ -54,35 +54,12 @@ using namespace clang; // Utility Methods for Preprocessor Directive Handling. //===----------------------------------------------------------------------===// -MacroInfo *Preprocessor::AllocateMacroInfo() { - MacroInfoChain *MIChain = BP.Allocate(); - MIChain->Next = MIChainHead; +MacroInfo *Preprocessor::AllocateMacroInfo(SourceLocation L) { + auto *MIChain = new (BP) MacroInfoChain{L, MIChainHead}; MIChainHead = MIChain; return &MIChain->MI; } -MacroInfo *Preprocessor::AllocateMacroInfo(SourceLocation L) { - MacroInfo *MI = AllocateMacroInfo(); - new (MI) MacroInfo(L); - return MI; -} - -MacroInfo *Preprocessor::AllocateDeserializedMacroInfo(SourceLocation L, - unsigned SubModuleID) { - static_assert(alignof(MacroInfo) >= sizeof(SubModuleID), - "alignment for MacroInfo is less than the ID"); - DeserializedMacroInfoChain *MIChain = - BP.Allocate(); - MIChain->Next = DeserialMIChainHead; - DeserialMIChainHead = MIChain; - - MacroInfo *MI = &MIChain->MI; - new (MI) MacroInfo(L); - MI->FromASTFile = true; - MI->setOwningModuleID(SubModuleID); - return MI; -} - DefMacroDirective *Preprocessor::AllocateDefMacroDirective(MacroInfo *MI, SourceLocation Loc) { return new (BP) DefMacroDirective(MI, Loc); diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp index e409ab036535..dce8c1efda23 100644 --- a/lib/Lex/Preprocessor.cpp +++ b/lib/Lex/Preprocessor.cpp @@ -88,7 +88,7 @@ Preprocessor::Preprocessor(std::shared_ptr PPOpts, CurDirLookup(nullptr), CurLexerKind(CLK_Lexer), CurLexerSubmodule(nullptr), Callbacks(nullptr), CurSubmoduleState(&NullSubmoduleState), MacroArgCache(nullptr), - Record(nullptr), MIChainHead(nullptr), DeserialMIChainHead(nullptr) { + Record(nullptr), MIChainHead(nullptr) { OwnsHeaderSearch = OwnsHeaders; CounterValue = 0; // __COUNTER__ starts at 0. @@ -169,11 +169,6 @@ Preprocessor::~Preprocessor() { std::fill(TokenLexerCache, TokenLexerCache + NumCachedTokenLexers, nullptr); CurTokenLexer.reset(); - while (DeserializedMacroInfoChain *I = DeserialMIChainHead) { - DeserialMIChainHead = I->Next; - I->~DeserializedMacroInfoChain(); - } - // Free any cached MacroArgs. for (MacroArgs *ArgList = MacroArgCache; ArgList;) ArgList = ArgList->deallocate(); diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 1465d21ac5ee..4ccee74eaa90 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -2577,9 +2577,9 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, // and attempt to recover. ParsedType T; IdentifierInfo *II = Tok.getIdentifierInfo(); + bool IsTemplateName = getLangOpts().CPlusPlus && NextToken().is(tok::less); Actions.DiagnoseUnknownTypeName(II, Loc, getCurScope(), SS, T, - getLangOpts().CPlusPlus && - NextToken().is(tok::less)); + IsTemplateName); if (T) { // The action has suggested that the type T could be used. Set that as // the type in the declaration specifiers, consume the would-be type @@ -2604,6 +2604,13 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, DS.SetRangeEnd(Tok.getLocation()); ConsumeToken(); + // Eat any following template arguments. + if (IsTemplateName) { + SourceLocation LAngle, RAngle; + TemplateArgList Args; + ParseTemplateIdAfterTemplateName(true, LAngle, Args, RAngle); + } + // TODO: Could inject an invalid typedef decl in an enclosing scope to // avoid rippling error messages on subsequent uses of the same type, // could be useful if #include was forgotten. diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index ad7b319676e9..e6cf65e36cfa 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -1137,8 +1137,8 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc, if (!Template) { TemplateArgList TemplateArgs; SourceLocation LAngleLoc, RAngleLoc; - ParseTemplateIdAfterTemplateName(nullptr, IdLoc, SS, true, LAngleLoc, - TemplateArgs, RAngleLoc); + ParseTemplateIdAfterTemplateName(true, LAngleLoc, TemplateArgs, + RAngleLoc); return true; } @@ -1530,8 +1530,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // a class (or template thereof). TemplateArgList TemplateArgs; SourceLocation LAngleLoc, RAngleLoc; - if (ParseTemplateIdAfterTemplateName( - nullptr, NameLoc, SS, true, LAngleLoc, TemplateArgs, RAngleLoc)) { + if (ParseTemplateIdAfterTemplateName(true, LAngleLoc, TemplateArgs, + RAngleLoc)) { // We couldn't parse the template argument list at all, so don't // try to give any location information for the list. LAngleLoc = RAngleLoc = SourceLocation(); diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 3e02e46ddc7d..727fd3500991 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -235,6 +235,30 @@ bool Parser::isNotExpressionStart() { return isKnownToBeDeclarationSpecifier(); } +/// We've parsed something that could plausibly be intended to be a template +/// name (\p LHS) followed by a '<' token, and the following code can't possibly +/// be an expression. Determine if this is likely to be a template-id and if so, +/// diagnose it. +bool Parser::diagnoseUnknownTemplateId(ExprResult LHS, SourceLocation Less) { + TentativeParsingAction TPA(*this); + // FIXME: We could look at the token sequence in a lot more detail here. + if (SkipUntil(tok::greater, tok::greatergreater, tok::greatergreatergreater, + StopAtSemi | StopBeforeMatch)) { + TPA.Commit(); + + SourceLocation Greater; + ParseGreaterThanInTemplateList(Greater, true, false); + Actions.diagnoseExprIntendedAsTemplateName(getCurScope(), LHS, + Less, Greater); + return true; + } + + // There's no matching '>' token, this probably isn't supposed to be + // interpreted as a template-id. Parse it as an (ill-formed) comparison. + TPA.Revert(); + return false; +} + static bool isFoldOperator(prec::Level Level) { return Level > prec::Unknown && Level != prec::Conditional; } @@ -276,6 +300,16 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { return LHS; } + // If a '<' token is followed by a type that can be a template argument and + // cannot be an expression, then this is ill-formed, but might be intended + // to be a template-id. + if (OpToken.is(tok::less) && Actions.mightBeIntendedToBeTemplateName(LHS) && + (isKnownToBeDeclarationSpecifier() || + Tok.isOneOf(tok::greater, tok::greatergreater, + tok::greatergreatergreater)) && + diagnoseUnknownTemplateId(LHS, OpToken.getLocation())) + return ExprError(); + // If the next token is an ellipsis, then this is a fold-expression. Leave // it alone so we can handle it in the paren expression. if (isFoldOperator(NextTokPrec) && Tok.is(tok::ellipsis)) { @@ -2989,6 +3023,11 @@ Optional Parser::ParseAvailabilitySpec() { return AvailabilitySpec(ConsumeToken()); } else { // Parse the platform name. + if (Tok.is(tok::code_completion)) { + Actions.CodeCompleteAvailabilityPlatformName(); + cutOffParsing(); + return None; + } if (Tok.isNot(tok::identifier)) { Diag(Tok, diag::err_avail_query_expected_platform_name); return None; @@ -3001,12 +3040,14 @@ Optional Parser::ParseAvailabilitySpec() { if (Version.empty()) return None; - StringRef Platform = PlatformIdentifier->Ident->getName(); + StringRef GivenPlatform = PlatformIdentifier->Ident->getName(); + StringRef Platform = + AvailabilityAttr::canonicalizePlatformName(GivenPlatform); if (AvailabilityAttr::getPrettyPlatformName(Platform).empty()) { Diag(PlatformIdentifier->Loc, diag::err_avail_query_unrecognized_platform_name) - << Platform; + << GivenPlatform; return None; } diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index 671a815911f3..56093f685617 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -2114,11 +2114,8 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, // Parse the enclosed template argument list. SourceLocation LAngleLoc, RAngleLoc; TemplateArgList TemplateArgs; - if (Tok.is(tok::less) && - ParseTemplateIdAfterTemplateName(Template, Id.StartLocation, - SS, true, LAngleLoc, - TemplateArgs, - RAngleLoc)) + if (Tok.is(tok::less) && ParseTemplateIdAfterTemplateName( + true, LAngleLoc, TemplateArgs, RAngleLoc)) return true; if (Id.getKind() == UnqualifiedId::IK_Identifier || diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp index d2b18e7c0a81..6a81e14ed496 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -886,22 +886,12 @@ bool Parser::ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc, /// list ('<' template-parameter-list [opt] '>') and placing the /// results into a form that can be transferred to semantic analysis. /// -/// \param Template the template declaration produced by isTemplateName -/// -/// \param TemplateNameLoc the source location of the template name -/// -/// \param SS if non-NULL, the nested-name-specifier preceding the -/// template name. -/// /// \param ConsumeLastToken if true, then we will consume the last /// token that forms the template-id. Otherwise, we will leave the /// last token in the stream (e.g., so that it can be replaced with an /// annotation token). bool -Parser::ParseTemplateIdAfterTemplateName(TemplateTy Template, - SourceLocation TemplateNameLoc, - const CXXScopeSpec &SS, - bool ConsumeLastToken, +Parser::ParseTemplateIdAfterTemplateName(bool ConsumeLastToken, SourceLocation &LAngleLoc, TemplateArgList &TemplateArgs, SourceLocation &RAngleLoc) { @@ -983,9 +973,7 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, // Parse the enclosed template argument list. SourceLocation LAngleLoc, RAngleLoc; TemplateArgList TemplateArgs; - bool Invalid = ParseTemplateIdAfterTemplateName(Template, - TemplateNameLoc, - SS, false, LAngleLoc, + bool Invalid = ParseTemplateIdAfterTemplateName(false, LAngleLoc, TemplateArgs, RAngleLoc); diff --git a/lib/Sema/CMakeLists.txt b/lib/Sema/CMakeLists.txt index 7a5973299f91..7d9ae621c93d 100644 --- a/lib/Sema/CMakeLists.txt +++ b/lib/Sema/CMakeLists.txt @@ -3,6 +3,7 @@ set(LLVM_LINK_COMPONENTS ) if (MSVC) + set_source_files_properties(SemaDeclAttr.cpp PROPERTIES COMPILE_FLAGS /bigobj) set_source_files_properties(SemaExpr.cpp PROPERTIES COMPILE_FLAGS /bigobj) endif() diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 2f493fa5fbef..ca1d27e9505f 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -477,6 +477,13 @@ static bool ShouldRemoveFromUnused(Sema *SemaRef, const DeclaratorDecl *D) { return true; if (const FunctionDecl *FD = dyn_cast(D)) { + // If this is a function template and none of its specializations is used, + // we should warn. + if (FunctionTemplateDecl *Template = FD->getDescribedFunctionTemplate()) + for (const auto *Spec : Template->specializations()) + if (ShouldRemoveFromUnused(SemaRef, Spec)) + return true; + // UnusedFileScopedDecls stores the first declaration. // The declaration may have become definition so check again. const FunctionDecl *DeclToCheck; @@ -500,6 +507,13 @@ static bool ShouldRemoveFromUnused(Sema *SemaRef, const DeclaratorDecl *D) { VD->isUsableInConstantExpressions(SemaRef->Context)) return true; + if (VarTemplateDecl *Template = VD->getDescribedVarTemplate()) + // If this is a variable template and none of its specializations is used, + // we should warn. + for (const auto *Spec : Template->specializations()) + if (ShouldRemoveFromUnused(SemaRef, Spec)) + return true; + // UnusedFileScopedDecls stores the first declaration. // The declaration may have become definition so check again. const VarDecl *DeclToCheck = VD->getDefinition(); @@ -905,10 +919,14 @@ void Sema::ActOnEndOfTranslationUnit() { << /*function*/0 << DiagD->getDeclName(); } } else { - Diag(DiagD->getLocation(), - isa(DiagD) ? diag::warn_unused_member_function - : diag::warn_unused_function) - << DiagD->getDeclName(); + if (FD->getDescribedFunctionTemplate()) + Diag(DiagD->getLocation(), diag::warn_unused_template) + << /*function*/0 << DiagD->getDeclName(); + else + Diag(DiagD->getLocation(), + isa(DiagD) ? diag::warn_unused_member_function + : diag::warn_unused_function) + << DiagD->getDeclName(); } } else { const VarDecl *DiagD = cast(*I)->getDefinition(); @@ -924,7 +942,11 @@ void Sema::ActOnEndOfTranslationUnit() { Diag(DiagD->getLocation(), diag::warn_unused_const_variable) << DiagD->getDeclName(); } else { - Diag(DiagD->getLocation(), diag::warn_unused_variable) + if (DiagD->getDescribedVarTemplate()) + Diag(DiagD->getLocation(), diag::warn_unused_template) + << /*variable*/1 << DiagD->getDeclName(); + else + Diag(DiagD->getLocation(), diag::warn_unused_variable) << DiagD->getDeclName(); } } diff --git a/lib/Sema/SemaCast.cpp b/lib/Sema/SemaCast.cpp index 7e91709e67da..7d534263f468 100644 --- a/lib/Sema/SemaCast.cpp +++ b/lib/Sema/SemaCast.cpp @@ -1871,7 +1871,8 @@ static bool fixOverloadedReinterpretCastExpr(Sema &Self, QualType DestType, // No guarantees that ResolveAndFixSingleFunctionTemplateSpecialization // preserves Result. Result = E; - if (!Self.resolveAndFixAddressOfOnlyViableOverloadCandidate(Result)) + if (!Self.resolveAndFixAddressOfOnlyViableOverloadCandidate( + Result, /*DoFunctionPointerConversion=*/true)) return false; return Result.isUsable(); } diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index cfac3f1dc1de..8fb2f4139236 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -3869,6 +3869,41 @@ static void AddObjCProperties( } } +static void AddRecordMembersCompletionResults(Sema &SemaRef, + ResultBuilder &Results, Scope *S, + QualType BaseType, + RecordDecl *RD) { + // Indicate that we are performing a member access, and the cv-qualifiers + // for the base object type. + Results.setObjectTypeQualifiers(BaseType.getQualifiers()); + + // Access to a C/C++ class, struct, or union. + Results.allowNestedNameSpecifiers(); + CodeCompletionDeclConsumer Consumer(Results, SemaRef.CurContext); + SemaRef.LookupVisibleDecls(RD, Sema::LookupMemberName, Consumer, + SemaRef.CodeCompleter->includeGlobals(), + /*IncludeDependentBases=*/true); + + if (SemaRef.getLangOpts().CPlusPlus) { + if (!Results.empty()) { + // The "template" keyword can follow "->" or "." in the grammar. + // However, we only want to suggest the template keyword if something + // is dependent. + bool IsDependent = BaseType->isDependentType(); + if (!IsDependent) { + for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent()) + if (DeclContext *Ctx = DepScope->getEntity()) { + IsDependent = Ctx->isDependentContext(); + break; + } + } + + if (IsDependent) + Results.AddResult(CodeCompletionResult("template")); + } + } +} + void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, SourceLocation OpLoc, bool IsArrow, bool IsBaseExprStatement) { @@ -3879,8 +3914,6 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, if (ConvertedBase.isInvalid()) return; Base = ConvertedBase.get(); - - typedef CodeCompletionResult Result; QualType BaseType = Base->getType(); @@ -3915,34 +3948,18 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, &ResultBuilder::IsMember); Results.EnterNewScope(); if (const RecordType *Record = BaseType->getAs()) { - // Indicate that we are performing a member access, and the cv-qualifiers - // for the base object type. - Results.setObjectTypeQualifiers(BaseType.getQualifiers()); - - // Access to a C/C++ class, struct, or union. - Results.allowNestedNameSpecifiers(); - CodeCompletionDeclConsumer Consumer(Results, CurContext); - LookupVisibleDecls(Record->getDecl(), LookupMemberName, Consumer, - CodeCompleter->includeGlobals()); - - if (getLangOpts().CPlusPlus) { - if (!Results.empty()) { - // The "template" keyword can follow "->" or "." in the grammar. - // However, we only want to suggest the template keyword if something - // is dependent. - bool IsDependent = BaseType->isDependentType(); - if (!IsDependent) { - for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent()) - if (DeclContext *Ctx = DepScope->getEntity()) { - IsDependent = Ctx->isDependentContext(); - break; - } - } - - if (IsDependent) - Results.AddResult(Result("template")); - } + AddRecordMembersCompletionResults(*this, Results, S, BaseType, + Record->getDecl()); + } else if (const auto *TST = BaseType->getAs()) { + TemplateName TN = TST->getTemplateName(); + if (const auto *TD = + dyn_cast_or_null(TN.getAsTemplateDecl())) { + CXXRecordDecl *RD = TD->getTemplatedDecl(); + AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD); } + } else if (const auto *ICNT = BaseType->getAs()) { + if (auto *RD = ICNT->getDecl()) + AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD); } else if (!IsArrow && BaseType->isObjCObjectPointerType()) { // Objective-C property reference. AddedPropertiesSet AddedProperties; @@ -7811,6 +7828,23 @@ void Sema::CodeCompleteNaturalLanguage() { nullptr, 0); } +void Sema::CodeCompleteAvailabilityPlatformName() { + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext::CCC_Other); + Results.EnterNewScope(); + static const char *Platforms[] = {"macOS", "iOS", "watchOS", "tvOS"}; + for (const char *Platform : llvm::makeArrayRef(Platforms)) { + Results.AddResult(CodeCompletionResult(Platform)); + Results.AddResult(CodeCompletionResult(Results.getAllocator().CopyString( + Twine(Platform) + "ApplicationExtension"))); + } + Results.ExitScope(); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, Results.data(), + Results.size()); +} + void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo, SmallVectorImpl &Results) { diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 2612023f59db..2e069a9defaa 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -64,22 +64,45 @@ namespace { class TypeNameValidatorCCC : public CorrectionCandidateCallback { public: - TypeNameValidatorCCC(bool AllowInvalid, bool WantClass=false, - bool AllowTemplates=false) - : AllowInvalidDecl(AllowInvalid), WantClassName(WantClass), - AllowTemplates(AllowTemplates) { - WantExpressionKeywords = false; - WantCXXNamedCasts = false; - WantRemainingKeywords = false; + TypeNameValidatorCCC(bool AllowInvalid, bool WantClass = false, + bool AllowTemplates = false, + bool AllowNonTemplates = true) + : AllowInvalidDecl(AllowInvalid), WantClassName(WantClass), + AllowTemplates(AllowTemplates), AllowNonTemplates(AllowNonTemplates) { + WantExpressionKeywords = false; + WantCXXNamedCasts = false; + WantRemainingKeywords = false; } bool ValidateCandidate(const TypoCorrection &candidate) override { if (NamedDecl *ND = candidate.getCorrectionDecl()) { + if (!AllowInvalidDecl && ND->isInvalidDecl()) + return false; + + if (getAsTypeTemplateDecl(ND)) + return AllowTemplates; + bool IsType = isa(ND) || isa(ND); - bool AllowedTemplate = AllowTemplates && getAsTypeTemplateDecl(ND); - return (IsType || AllowedTemplate) && - (AllowInvalidDecl || !ND->isInvalidDecl()); + if (!IsType) + return false; + + if (AllowNonTemplates) + return true; + + // An injected-class-name of a class template (specialization) is valid + // as a template or as a non-template. + if (AllowTemplates) { + auto *RD = dyn_cast(ND); + if (!RD || !RD->isInjectedClassName()) + return false; + RD = cast(RD->getDeclContext()); + return RD->getDescribedClassTemplate() || + isa(RD); + } + + return false; } + return !WantClassName && candidate.isKeyword(); } @@ -87,6 +110,7 @@ class TypeNameValidatorCCC : public CorrectionCandidateCallback { bool AllowInvalidDecl; bool WantClassName; bool AllowTemplates; + bool AllowNonTemplates; }; } // end anonymous namespace @@ -627,7 +651,7 @@ void Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II, Scope *S, CXXScopeSpec *SS, ParsedType &SuggestedType, - bool AllowClassTemplates) { + bool IsTemplateName) { // Don't report typename errors for editor placeholders. if (II->isEditorPlaceholder()) return; @@ -639,28 +663,41 @@ void Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II, if (TypoCorrection Corrected = CorrectTypo(DeclarationNameInfo(II, IILoc), LookupOrdinaryName, S, SS, llvm::make_unique( - false, false, AllowClassTemplates), + false, false, IsTemplateName, !IsTemplateName), CTK_ErrorRecovery)) { + // FIXME: Support error recovery for the template-name case. + bool CanRecover = !IsTemplateName; if (Corrected.isKeyword()) { // We corrected to a keyword. - diagnoseTypo(Corrected, PDiag(diag::err_unknown_typename_suggest) << II); + diagnoseTypo(Corrected, + PDiag(IsTemplateName ? diag::err_no_template_suggest + : diag::err_unknown_typename_suggest) + << II); II = Corrected.getCorrectionAsIdentifierInfo(); } else { // We found a similarly-named type or interface; suggest that. if (!SS || !SS->isSet()) { diagnoseTypo(Corrected, - PDiag(diag::err_unknown_typename_suggest) << II); + PDiag(IsTemplateName ? diag::err_no_template_suggest + : diag::err_unknown_typename_suggest) + << II, CanRecover); } else if (DeclContext *DC = computeDeclContext(*SS, false)) { std::string CorrectedStr(Corrected.getAsString(getLangOpts())); bool DroppedSpecifier = Corrected.WillReplaceSpecifier() && II->getName().equals(CorrectedStr); diagnoseTypo(Corrected, - PDiag(diag::err_unknown_nested_typename_suggest) - << II << DC << DroppedSpecifier << SS->getRange()); + PDiag(IsTemplateName + ? diag::err_no_member_template_suggest + : diag::err_unknown_nested_typename_suggest) + << II << DC << DroppedSpecifier << SS->getRange(), + CanRecover); } else { llvm_unreachable("could not have corrected a typo here"); } + if (!CanRecover) + return; + CXXScopeSpec tmpSS; if (Corrected.getCorrectionSpecifier()) tmpSS.MakeTrivial(Context, Corrected.getCorrectionSpecifier(), @@ -675,7 +712,7 @@ void Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II, return; } - if (getLangOpts().CPlusPlus) { + if (getLangOpts().CPlusPlus && !IsTemplateName) { // See if II is a class template that the user forgot to pass arguments to. UnqualifiedId Name; Name.setIdentifier(II, IILoc); @@ -700,10 +737,13 @@ void Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II, // (struct, union, enum) from Parser::ParseImplicitInt here, instead? if (!SS || (!SS->isSet() && !SS->isInvalid())) - Diag(IILoc, diag::err_unknown_typename) << II; + Diag(IILoc, IsTemplateName ? diag::err_no_template + : diag::err_unknown_typename) + << II; else if (DeclContext *DC = computeDeclContext(*SS, false)) - Diag(IILoc, diag::err_typename_nested_not_found) - << II << DC << SS->getRange(); + Diag(IILoc, IsTemplateName ? diag::err_no_member_template + : diag::err_typename_nested_not_found) + << II << DC << SS->getRange(); else if (isDependentScopeSpecifier(*SS)) { unsigned DiagID = diag::err_typename_missing; if (getLangOpts().MSVCCompat && isMicrosoftMissingTypename(SS, S)) @@ -1488,6 +1528,11 @@ bool Sema::ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const { if (const FunctionDecl *FD = dyn_cast(D)) { if (FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) return false; + // A non-out-of-line declaration of a member specialization was implicitly + // instantiated; it's the out-of-line declaration that we're interested in. + if (FD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization && + FD->getMemberSpecializationInfo() && !FD->isOutOfLine()) + return false; if (const CXXMethodDecl *MD = dyn_cast(FD)) { if (MD->isVirtual() || IsDisallowedCopyOrAssign(MD)) @@ -1514,6 +1559,10 @@ bool Sema::ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const { if (VD->isStaticDataMember() && VD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) return false; + if (VD->isStaticDataMember() && + VD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization && + VD->getMemberSpecializationInfo() && !VD->isOutOfLine()) + return false; if (VD->isInline() && !isMainFileLoc(*this, VD->getLocation())) return false; @@ -1972,7 +2021,7 @@ bool Sema::isIncompatibleTypedef(TypeDecl *Old, TypedefNameDecl *New) { Diag(New->getLocation(), diag::err_redefinition_variably_modified_typedef) << Kind << NewType; if (Old->getLocation().isValid()) - Diag(Old->getLocation(), diag::note_previous_definition); + notePreviousDefinition(Old->getLocation(), New->getLocation()); New->setInvalidDecl(); return true; } @@ -1985,7 +2034,7 @@ bool Sema::isIncompatibleTypedef(TypeDecl *Old, TypedefNameDecl *New) { Diag(New->getLocation(), diag::err_redefinition_different_typedef) << Kind << NewType << OldType; if (Old->getLocation().isValid()) - Diag(Old->getLocation(), diag::note_previous_definition); + notePreviousDefinition(Old->getLocation(), New->getLocation()); New->setInvalidDecl(); return true; } @@ -2052,7 +2101,7 @@ void Sema::MergeTypedefNameDecl(Scope *S, TypedefNameDecl *New, NamedDecl *OldD = OldDecls.getRepresentativeDecl(); if (OldD->getLocation().isValid()) - Diag(OldD->getLocation(), diag::note_previous_definition); + notePreviousDefinition(OldD->getLocation(), New->getLocation()); return New->setInvalidDecl(); } @@ -2078,7 +2127,7 @@ void Sema::MergeTypedefNameDecl(Scope *S, TypedefNameDecl *New, New->setTypeSourceInfo(OldTD->getTypeSourceInfo()); // Make the old tag definition visible. - makeMergedDefinitionVisible(Hidden, NewTag->getLocation()); + makeMergedDefinitionVisible(Hidden); // If this was an unscoped enumeration, yank all of its enumerators // out of the scope. @@ -2144,7 +2193,7 @@ void Sema::MergeTypedefNameDecl(Scope *S, TypedefNameDecl *New, Diag(New->getLocation(), diag::err_redefinition) << New->getDeclName(); - Diag(Old->getLocation(), diag::note_previous_definition); + notePreviousDefinition(Old->getLocation(), New->getLocation()); return New->setInvalidDecl(); } @@ -2165,7 +2214,7 @@ void Sema::MergeTypedefNameDecl(Scope *S, TypedefNameDecl *New, Diag(New->getLocation(), diag::ext_redefinition_of_typedef) << New->getDeclName(); - Diag(Old->getLocation(), diag::note_previous_definition); + notePreviousDefinition(Old->getLocation(), New->getLocation()); } /// DeclhasAttr - returns true if decl Declaration already has the target @@ -2452,7 +2501,10 @@ static void checkNewAttributesAfterDef(Sema &S, Decl *New, const Decl *Old) { ? diag::err_alias_after_tentative : diag::err_redefinition; S.Diag(VD->getLocation(), Diag) << VD->getDeclName(); - S.Diag(Def->getLocation(), diag::note_previous_definition); + if (Diag == diag::err_redefinition) + S.notePreviousDefinition(Def->getLocation(), VD->getLocation()); + else + S.Diag(Def->getLocation(), diag::note_previous_definition); VD->setInvalidDecl(); } ++I; @@ -2839,7 +2891,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, } else { Diag(New->getLocation(), diag::err_redefinition_different_kind) << New->getDeclName(); - Diag(OldD->getLocation(), diag::note_previous_definition); + notePreviousDefinition(OldD->getLocation(), New->getLocation()); return true; } } @@ -2876,7 +2928,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, !Old->hasAttr()) { Diag(New->getLocation(), diag::err_internal_linkage_redeclaration) << New->getDeclName(); - Diag(Old->getLocation(), diag::note_previous_definition); + notePreviousDefinition(Old->getLocation(), New->getLocation()); New->dropAttr(); } @@ -3604,9 +3656,9 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { } if (!Old) { Diag(New->getLocation(), diag::err_redefinition_different_kind) - << New->getDeclName(); - Diag(Previous.getRepresentativeDecl()->getLocation(), - diag::note_previous_definition); + << New->getDeclName(); + notePreviousDefinition(Previous.getRepresentativeDecl()->getLocation(), + New->getLocation()); return New->setInvalidDecl(); } @@ -3635,7 +3687,7 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { Old->getStorageClass() == SC_None && !Old->hasAttr()) { Diag(New->getLocation(), diag::warn_weak_import) << New->getDeclName(); - Diag(Old->getLocation(), diag::note_previous_definition); + notePreviousDefinition(Old->getLocation(), New->getLocation()); // Remove weak_import attribute on new declaration. New->dropAttr(); } @@ -3644,7 +3696,7 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { !Old->hasAttr()) { Diag(New->getLocation(), diag::err_internal_linkage_redeclaration) << New->getDeclName(); - Diag(Old->getLocation(), diag::note_previous_definition); + notePreviousDefinition(Old->getLocation(), New->getLocation()); New->dropAttr(); } @@ -3801,6 +3853,67 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { New->setImplicitlyInline(); } +void Sema::notePreviousDefinition(SourceLocation Old, SourceLocation New) { + SourceManager &SrcMgr = getSourceManager(); + auto FNewDecLoc = SrcMgr.getDecomposedLoc(New); + auto FOldDecLoc = SrcMgr.getDecomposedLoc(Old); + auto *FNew = SrcMgr.getFileEntryForID(FNewDecLoc.first); + auto *FOld = SrcMgr.getFileEntryForID(FOldDecLoc.first); + auto &HSI = PP.getHeaderSearchInfo(); + StringRef HdrFilename = SrcMgr.getFilename(SrcMgr.getSpellingLoc(Old)); + + auto noteFromModuleOrInclude = [&](SourceLocation &Loc, + SourceLocation &IncLoc) -> bool { + Module *Mod = nullptr; + // Redefinition errors with modules are common with non modular mapped + // headers, example: a non-modular header H in module A that also gets + // included directly in a TU. Pointing twice to the same header/definition + // is confusing, try to get better diagnostics when modules is on. + if (getLangOpts().Modules) { + auto ModLoc = SrcMgr.getModuleImportLoc(Old); + if (!ModLoc.first.isInvalid()) + Mod = HSI.getModuleMap().inferModuleFromLocation( + FullSourceLoc(Loc, SrcMgr)); + } + + if (IncLoc.isValid()) { + if (Mod) { + Diag(IncLoc, diag::note_redefinition_modules_same_file) + << HdrFilename.str() << Mod->getFullModuleName(); + if (!Mod->DefinitionLoc.isInvalid()) + Diag(Mod->DefinitionLoc, diag::note_defined_here) + << Mod->getFullModuleName(); + } else { + Diag(IncLoc, diag::note_redefinition_include_same_file) + << HdrFilename.str(); + } + return true; + } + + return false; + }; + + // Is it the same file and same offset? Provide more information on why + // this leads to a redefinition error. + bool EmittedDiag = false; + if (FNew == FOld && FNewDecLoc.second == FOldDecLoc.second) { + SourceLocation OldIncLoc = SrcMgr.getIncludeLoc(FOldDecLoc.first); + SourceLocation NewIncLoc = SrcMgr.getIncludeLoc(FNewDecLoc.first); + EmittedDiag = noteFromModuleOrInclude(Old, OldIncLoc); + EmittedDiag |= noteFromModuleOrInclude(New, NewIncLoc); + + // If the header has no guards, emit a note suggesting one. + if (FOld && !HSI.isFileMultipleIncludeGuarded(FOld)) + Diag(Old, diag::note_use_ifdef_guards); + + if (EmittedDiag) + return; + } + + // Redefinition coming from different files or couldn't do better above. + Diag(Old, diag::note_previous_definition); +} + /// We've just determined that \p Old and \p New both appear to be definitions /// of the same variable. Either diagnose or fix the problem. bool Sema::checkVarDeclRedefinition(VarDecl *Old, VarDecl *New) { @@ -3816,12 +3929,12 @@ bool Sema::checkVarDeclRedefinition(VarDecl *Old, VarDecl *New) { // Make the canonical definition visible. if (auto *OldTD = Old->getDescribedVarTemplate()) - makeMergedDefinitionVisible(OldTD, New->getLocation()); - makeMergedDefinitionVisible(Old, New->getLocation()); + makeMergedDefinitionVisible(OldTD); + makeMergedDefinitionVisible(Old); return false; } else { Diag(New->getLocation(), diag::err_redefinition) << New; - Diag(Old->getLocation(), diag::note_previous_definition); + notePreviousDefinition(Old->getLocation(), New->getLocation()); New->setInvalidDecl(); return true; } @@ -6706,6 +6819,9 @@ NamedDecl *Sema::ActOnVariableDeclarator( return NewTemplate; } + if (IsMemberSpecialization && !NewVD->isInvalidDecl()) + CompleteMemberSpecialization(NewVD, Previous); + return NewVD; } @@ -8919,12 +9035,17 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, } } + MarkUnusedFileScopedDecl(NewFD); + if (getLangOpts().CPlusPlus) { if (FunctionTemplate) { if (NewFD->isInvalidDecl()) FunctionTemplate->setInvalidDecl(); return FunctionTemplate; } + + if (isMemberSpecialization && !NewFD->isInvalidDecl()) + CompleteMemberSpecialization(NewFD, Previous); } if (NewFD->hasAttr()) { @@ -8964,8 +9085,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, } } - MarkUnusedFileScopedDecl(NewFD); - // Here we have an function template explicit specialization at class scope. // The actually specialization will be postponed to template instatiation // time via the ClassScopeFunctionSpecializationDecl node. @@ -9182,7 +9301,9 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, if (OldTemplateDecl->getTemplatedDecl()->isDeleted()) { FunctionDecl *const OldTemplatedDecl = OldTemplateDecl->getTemplatedDecl(); + // FIXME: This assert will not hold in the presence of modules. assert(OldTemplatedDecl->getCanonicalDecl() == OldTemplatedDecl); + // FIXME: We need an update record for this AST mutation. OldTemplatedDecl->setDeletedAsWritten(false); } } @@ -10273,23 +10394,36 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { VDecl->setInit(Init); if (VDecl->isLocalVarDecl()) { + // Don't check the initializer if the declaration is malformed. + if (VDecl->isInvalidDecl()) { + // do nothing + + // OpenCL v1.2 s6.5.3: __constant locals must be constant-initialized. + // This is true even in OpenCL C++. + } else if (VDecl->getType().getAddressSpace() == LangAS::opencl_constant) { + CheckForConstantInitializer(Init, DclT); + + // Otherwise, C++ does not restrict the initializer. + } else if (getLangOpts().CPlusPlus) { + // do nothing + // C99 6.7.8p4: All the expressions in an initializer for an object that has // static storage duration shall be constant expressions or string literals. - // C++ does not have this restriction. - if (!getLangOpts().CPlusPlus && !VDecl->isInvalidDecl()) { + } else if (VDecl->getStorageClass() == SC_Static) { + CheckForConstantInitializer(Init, DclT); + + // C89 is stricter than C99 for aggregate initializers. + // C89 6.5.7p3: All the expressions [...] in an initializer list + // for an object that has aggregate or union type shall be + // constant expressions. + } else if (!getLangOpts().C99 && VDecl->getType()->isAggregateType() && + isa(Init)) { const Expr *Culprit; - if (VDecl->getStorageClass() == SC_Static) - CheckForConstantInitializer(Init, DclT); - // C89 is stricter than C99 for non-static aggregate types. - // C89 6.5.7p3: All the expressions [...] in an initializer list - // for an object that has aggregate or union type shall be - // constant expressions. - else if (!getLangOpts().C99 && VDecl->getType()->isAggregateType() && - isa(Init) && - !Init->isConstantInitializer(Context, false, &Culprit)) + if (!Init->isConstantInitializer(Context, false, &Culprit)) { Diag(Culprit->getExprLoc(), diag::ext_aggregate_init_not_constant) << Culprit->getSourceRange(); + } } } else if (VDecl->isStaticDataMember() && !VDecl->isInline() && VDecl->getLexicalDeclContext()->isRecord()) { @@ -11023,8 +11157,7 @@ static bool hasDependentAlignment(VarDecl *VD) { /// FinalizeDeclaration - called by ParseDeclarationAfterDeclarator to perform /// any semantic actions necessary after any initializer has been attached. -void -Sema::FinalizeDeclaration(Decl *ThisDecl) { +void Sema::FinalizeDeclaration(Decl *ThisDecl) { // Note that we are no longer parsing the initializer for this declaration. ParsingInitForAutoVars.erase(ThisDecl); @@ -11189,9 +11322,8 @@ Sema::FinalizeDeclaration(Decl *ThisDecl) { if (DC->getRedeclContext()->isFileContext() && VD->isExternallyVisible()) AddPushedVisibilityAttribute(VD); - // FIXME: Warn on unused templates. - if (VD->isFileVarDecl() && !VD->getDescribedVarTemplate() && - !isa(VD)) + // FIXME: Warn on unused var template partial specializations. + if (VD->isFileVarDecl() && !isa(VD)) MarkUnusedFileScopedDecl(VD); // Now we have parsed the initializer and can update the table of magic @@ -11765,9 +11897,8 @@ Sema::CheckForFunctionRedefinition(FunctionDecl *FD, Definition->getNumTemplateParameterLists())) { SkipBody->ShouldSkip = true; if (auto *TD = Definition->getDescribedFunctionTemplate()) - makeMergedDefinitionVisible(TD, FD->getLocation()); - makeMergedDefinitionVisible(const_cast(Definition), - FD->getLocation()); + makeMergedDefinitionVisible(TD); + makeMergedDefinitionVisible(const_cast(Definition)); return; } @@ -13421,7 +13552,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // we already have. Make the existing definition visible and // use it in place of this one. SkipBody->ShouldSkip = true; - makeMergedDefinitionVisible(Hidden, KWLoc); + makeMergedDefinitionVisible(Hidden); return Def; } else if (!IsExplicitSpecializationAfterInstantiation) { // A redeclaration in function prototype scope in C isn't @@ -13430,7 +13561,8 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, Diag(NameLoc, diag::warn_redefinition_in_param_list) << Name; else Diag(NameLoc, diag::err_redefinition) << Name; - Diag(Def->getLocation(), diag::note_previous_definition); + notePreviousDefinition(Def->getLocation(), + NameLoc.isValid() ? NameLoc : KWLoc); // If this is a redefinition, recover by making this // struct be anonymous, which will make any later // references get the previous definition. @@ -13520,7 +13652,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // The tag name clashes with something else in the target scope, // issue an error and recover by making this tag be anonymous. Diag(NameLoc, diag::err_redefinition_different_kind) << Name; - Diag(PrevDecl->getLocation(), diag::note_previous_definition); + notePreviousDefinition(PrevDecl->getLocation(), NameLoc); Name = nullptr; Invalid = true; } @@ -13753,6 +13885,9 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // record. AddPushedVisibilityAttribute(New); + if (isMemberSpecialization && !New->isInvalidDecl()) + CompleteMemberSpecialization(New, Previous); + OwnedDecl = true; // In C++, don't return an invalid declaration. We can't recover well from // the cases where we make the type anonymous. @@ -15221,7 +15356,7 @@ Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst, Diag(IdLoc, diag::err_redefinition_of_enumerator) << Id; else Diag(IdLoc, diag::err_redefinition) << Id; - Diag(PrevDecl->getLocation(), diag::note_previous_definition); + notePreviousDefinition(PrevDecl->getLocation(), IdLoc); return nullptr; } } diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 97d273f6ddb6..3de792e4e406 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -7230,6 +7230,13 @@ class DiagnoseUnguardedAvailability SemaRef.Context.getTargetInfo().getPlatformMinVersion()); } + bool TraverseDecl(Decl *D) { + // Avoid visiting nested functions to prevent duplicate warnings. + if (!D || isa(D)) + return true; + return Base::TraverseDecl(D); + } + bool TraverseStmt(Stmt *S) { if (!S) return true; @@ -7243,6 +7250,8 @@ class DiagnoseUnguardedAvailability bool TraverseIfStmt(IfStmt *If); + bool TraverseLambdaExpr(LambdaExpr *E) { return true; } + bool VisitObjCMessageExpr(ObjCMessageExpr *Msg) { if (ObjCMethodDecl *D = Msg->getMethodDecl()) DiagnoseDeclAvailability( @@ -7346,7 +7355,9 @@ void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability( llvm::raw_string_ostream FixItOS(FixItString); FixItOS << "if (" << (SemaRef.getLangOpts().ObjC1 ? "@available" : "__builtin_available") - << "(" << SemaRef.getASTContext().getTargetInfo().getPlatformName() + << "(" + << AvailabilityAttr::getPlatformNameSourceSpelling( + SemaRef.getASTContext().getTargetInfo().getPlatformName()) << " " << Introduced.getAsString() << ", *)) {\n" << Indentation << ExtraIndentation; FixitDiag << FixItHint::CreateInsertion(IfInsertionLoc, FixItOS.str()); diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 849e978e2d86..14efc9672061 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -5277,6 +5277,9 @@ ExprResult Sema::ActOnCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc, // We aren't supposed to apply this logic if there's an '&' involved. if (!find.HasFormOfMemberPointer) { + if (Expr::hasAnyTypeDependentArguments(ArgExprs)) + return new (Context) CallExpr( + Context, Fn, ArgExprs, Context.DependentTy, VK_RValue, RParenLoc); OverloadExpr *ovl = find.Expression; if (UnresolvedLookupExpr *ULE = dyn_cast(ovl)) return BuildOverloadedCallExpr( @@ -8028,6 +8031,33 @@ QualType Sema::InvalidOperands(SourceLocation Loc, ExprResult &LHS, return QualType(); } +// Diagnose cases where a scalar was implicitly converted to a vector and +// diagnose the underlying types. Otherwise, diagnose the error +// as invalid vector logical operands for non-C++ cases. +QualType Sema::InvalidLogicalVectorOperands(SourceLocation Loc, ExprResult &LHS, + ExprResult &RHS) { + QualType LHSType = LHS.get()->IgnoreImpCasts()->getType(); + QualType RHSType = RHS.get()->IgnoreImpCasts()->getType(); + + bool LHSNatVec = LHSType->isVectorType(); + bool RHSNatVec = RHSType->isVectorType(); + + if (!(LHSNatVec && RHSNatVec)) { + Expr *Vector = LHSNatVec ? LHS.get() : RHS.get(); + Expr *NonVector = !LHSNatVec ? LHS.get() : RHS.get(); + Diag(Loc, diag::err_typecheck_logical_vector_expr_gnu_cpp_restrict) + << 0 << Vector->getType() << NonVector->IgnoreImpCasts()->getType() + << Vector->getSourceRange(); + return QualType(); + } + + Diag(Loc, diag::err_typecheck_logical_vector_expr_gnu_cpp_restrict) + << 1 << LHSType << RHSType << LHS.get()->getSourceRange() + << RHS.get()->getSourceRange(); + + return QualType(); +} + /// Try to convert a value of non-vector type to a vector type by converting /// the type to the element type of the vector and then performing a splat. /// If the language is OpenCL, we only use conversions that promote scalar @@ -8075,6 +8105,162 @@ static bool tryVectorConvertAndSplat(Sema &S, ExprResult *scalar, return false; } +/// Test if a (constant) integer Int can be casted to another integer type +/// IntTy without losing precision. +static bool canConvertIntToOtherIntTy(Sema &S, ExprResult *Int, + QualType OtherIntTy) { + QualType IntTy = Int->get()->getType().getUnqualifiedType(); + + // Reject cases where the value of the Int is unknown as that would + // possibly cause truncation, but accept cases where the scalar can be + // demoted without loss of precision. + llvm::APSInt Result; + bool CstInt = Int->get()->EvaluateAsInt(Result, S.Context); + int Order = S.Context.getIntegerTypeOrder(OtherIntTy, IntTy); + bool IntSigned = IntTy->hasSignedIntegerRepresentation(); + bool OtherIntSigned = OtherIntTy->hasSignedIntegerRepresentation(); + + if (CstInt) { + // If the scalar is constant and is of a higher order and has more active + // bits that the vector element type, reject it. + unsigned NumBits = IntSigned + ? (Result.isNegative() ? Result.getMinSignedBits() + : Result.getActiveBits()) + : Result.getActiveBits(); + if (Order < 0 && S.Context.getIntWidth(OtherIntTy) < NumBits) + return true; + + // If the signedness of the scalar type and the vector element type + // differs and the number of bits is greater than that of the vector + // element reject it. + return (IntSigned != OtherIntSigned && + NumBits > S.Context.getIntWidth(OtherIntTy)); + } + + // Reject cases where the value of the scalar is not constant and it's + // order is greater than that of the vector element type. + return (Order < 0); +} + +/// Test if a (constant) integer Int can be casted to floating point type +/// FloatTy without losing precision. +static bool canConvertIntTyToFloatTy(Sema &S, ExprResult *Int, + QualType FloatTy) { + QualType IntTy = Int->get()->getType().getUnqualifiedType(); + + // Determine if the integer constant can be expressed as a floating point + // number of the appropiate type. + llvm::APSInt Result; + bool CstInt = Int->get()->EvaluateAsInt(Result, S.Context); + uint64_t Bits = 0; + if (CstInt) { + // Reject constants that would be truncated if they were converted to + // the floating point type. Test by simple to/from conversion. + // FIXME: Ideally the conversion to an APFloat and from an APFloat + // could be avoided if there was a convertFromAPInt method + // which could signal back if implicit truncation occurred. + llvm::APFloat Float(S.Context.getFloatTypeSemantics(FloatTy)); + Float.convertFromAPInt(Result, IntTy->hasSignedIntegerRepresentation(), + llvm::APFloat::rmTowardZero); + llvm::APSInt ConvertBack(S.Context.getIntWidth(IntTy), + !IntTy->hasSignedIntegerRepresentation()); + bool Ignored = false; + Float.convertToInteger(ConvertBack, llvm::APFloat::rmNearestTiesToEven, + &Ignored); + if (Result != ConvertBack) + return true; + } else { + // Reject types that cannot be fully encoded into the mantissa of + // the float. + Bits = S.Context.getTypeSize(IntTy); + unsigned FloatPrec = llvm::APFloat::semanticsPrecision( + S.Context.getFloatTypeSemantics(FloatTy)); + if (Bits > FloatPrec) + return true; + } + + return false; +} + +/// Attempt to convert and splat Scalar into a vector whose types matches +/// Vector following GCC conversion rules. The rule is that implicit +/// conversion can occur when Scalar can be casted to match Vector's element +/// type without causing truncation of Scalar. +static bool tryGCCVectorConvertAndSplat(Sema &S, ExprResult *Scalar, + ExprResult *Vector) { + QualType ScalarTy = Scalar->get()->getType().getUnqualifiedType(); + QualType VectorTy = Vector->get()->getType().getUnqualifiedType(); + const VectorType *VT = VectorTy->getAs(); + + assert(!isa(VT) && + "ExtVectorTypes should not be handled here!"); + + QualType VectorEltTy = VT->getElementType(); + + // Reject cases where the vector element type or the scalar element type are + // not integral or floating point types. + if (!VectorEltTy->isArithmeticType() || !ScalarTy->isArithmeticType()) + return true; + + // The conversion to apply to the scalar before splatting it, + // if necessary. + CastKind ScalarCast = CK_NoOp; + + // Accept cases where the vector elements are integers and the scalar is + // an integer. + // FIXME: Notionally if the scalar was a floating point value with a precise + // integral representation, we could cast it to an appropriate integer + // type and then perform the rest of the checks here. GCC will perform + // this conversion in some cases as determined by the input language. + // We should accept it on a language independent basis. + if (VectorEltTy->isIntegralType(S.Context) && + ScalarTy->isIntegralType(S.Context) && + S.Context.getIntegerTypeOrder(VectorEltTy, ScalarTy)) { + + if (canConvertIntToOtherIntTy(S, Scalar, VectorEltTy)) + return true; + + ScalarCast = CK_IntegralCast; + } else if (VectorEltTy->isRealFloatingType()) { + if (ScalarTy->isRealFloatingType()) { + + // Reject cases where the scalar type is not a constant and has a higher + // Order than the vector element type. + llvm::APFloat Result(0.0); + bool CstScalar = Scalar->get()->EvaluateAsFloat(Result, S.Context); + int Order = S.Context.getFloatingTypeOrder(VectorEltTy, ScalarTy); + if (!CstScalar && Order < 0) + return true; + + // If the scalar cannot be safely casted to the vector element type, + // reject it. + if (CstScalar) { + bool Truncated = false; + Result.convert(S.Context.getFloatTypeSemantics(VectorEltTy), + llvm::APFloat::rmNearestTiesToEven, &Truncated); + if (Truncated) + return true; + } + + ScalarCast = CK_FloatingCast; + } else if (ScalarTy->isIntegralType(S.Context)) { + if (canConvertIntTyToFloatTy(S, Scalar, VectorEltTy)) + return true; + + ScalarCast = CK_IntegralToFloating; + } else + return true; + } + + // Adjust scalar if desired. + if (Scalar) { + if (ScalarCast != CK_NoOp) + *Scalar = S.ImpCastExprToType(Scalar->get(), VectorEltTy, ScalarCast); + *Scalar = S.ImpCastExprToType(Scalar->get(), VectorTy, CK_VectorSplat); + } + return false; +} + QualType Sema::CheckVectorOperands(ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, bool IsCompAssign, bool AllowBothBool, @@ -8143,19 +8329,29 @@ QualType Sema::CheckVectorOperands(ExprResult &LHS, ExprResult &RHS, } } - // If there's an ext-vector type and a scalar, try to convert the scalar to + // If there's a vector type and a scalar, try to convert the scalar to // the vector element type and splat. - // FIXME: this should also work for regular vector types as supported in GCC. - if (!RHSVecType && isa(LHSVecType)) { - if (!tryVectorConvertAndSplat(*this, &RHS, RHSType, - LHSVecType->getElementType(), LHSType)) - return LHSType; + if (!RHSVecType) { + if (isa(LHSVecType)) { + if (!tryVectorConvertAndSplat(*this, &RHS, RHSType, + LHSVecType->getElementType(), LHSType)) + return LHSType; + } else { + if (!tryGCCVectorConvertAndSplat(*this, &RHS, &LHS)) + return LHSType; + } } - if (!LHSVecType && isa(RHSVecType)) { - if (!tryVectorConvertAndSplat(*this, (IsCompAssign ? nullptr : &LHS), - LHSType, RHSVecType->getElementType(), - RHSType)) - return RHSType; + if (!LHSVecType) { + if (isa(RHSVecType)) { + if (!tryVectorConvertAndSplat(*this, (IsCompAssign ? nullptr : &LHS), + LHSType, RHSVecType->getElementType(), + RHSType)) + return RHSType; + } else { + if (LHS.get()->getValueKind() == VK_LValue || + !tryGCCVectorConvertAndSplat(*this, &LHS, &RHS)) + return RHSType; + } } // FIXME: The code below also handles conversion between vectors and @@ -8208,6 +8404,22 @@ QualType Sema::CheckVectorOperands(ExprResult &LHS, ExprResult &RHS, return QualType(); } + + // If there is a vector type that is not a ExtVector and a scalar, we reach + // this point if scalar could not be converted to the vector's element type + // without truncation. + if ((RHSVecType && !isa(RHSVecType)) || + (LHSVecType && !isa(LHSVecType))) { + QualType Scalar = LHSVecType ? RHSType : LHSType; + QualType Vector = LHSVecType ? LHSType : RHSType; + unsigned ScalarOrVector = LHSVecType && RHSVecType ? 1 : 0; + Diag(Loc, + diag::err_typecheck_vector_not_convertable_implict_truncation) + << ScalarOrVector << Scalar << Vector; + + return QualType(); + } + // Otherwise, use the generic diagnostic. Diag(Loc, diag::err_typecheck_vector_not_convertable) << LHSType << RHSType @@ -9827,6 +10039,12 @@ QualType Sema::CheckVectorLogicalOperands(ExprResult &LHS, ExprResult &RHS, if (getLangOpts().OpenCL && getLangOpts().OpenCLVersion < 120 && vType->hasFloatingRepresentation()) return InvalidOperands(Loc, LHS, RHS); + // FIXME: The check for C++ here is for GCC compatibility. GCC rejects the + // usage of the logical operators && and || with vectors in C. This + // check could be notionally dropped. + if (!getLangOpts().CPlusPlus && + !(isa(vType->getAs()))) + return InvalidLogicalVectorOperands(Loc, LHS, RHS); return GetSignedVectorType(LHS.get()->getType()); } @@ -11770,6 +11988,8 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, resultType = GetSignedVectorType(resultType); break; } else { + // FIXME: GCC's vector extension permits the usage of '!' with a vector + // type in C++. We should allow that here too. return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) << resultType << Input.get()->getSourceRange()); } diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 9b88cddbc969..8500b748a3ec 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -4720,10 +4720,24 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, QualType LhsT, // regard to cv-qualifiers. const RecordType *lhsRecord = LhsT->getAs(); - if (!lhsRecord) return false; - const RecordType *rhsRecord = RhsT->getAs(); - if (!rhsRecord) return false; + if (!rhsRecord || !lhsRecord) { + const ObjCObjectType *LHSObjTy = LhsT->getAs(); + const ObjCObjectType *RHSObjTy = RhsT->getAs(); + if (!LHSObjTy || !RHSObjTy) + return false; + + ObjCInterfaceDecl *BaseInterface = LHSObjTy->getInterface(); + ObjCInterfaceDecl *DerivedInterface = RHSObjTy->getInterface(); + if (!BaseInterface || !DerivedInterface) + return false; + + if (Self.RequireCompleteType( + KeyLoc, RhsT, diag::err_incomplete_type_used_in_type_trait_expr)) + return false; + + return BaseInterface->isSuperClassOf(DerivedInterface); + } assert(Self.Context.hasSameUnqualifiedType(LhsT, RhsT) == (lhsRecord == rhsRecord)); @@ -5342,6 +5356,15 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, // C++11 [expr.cond]p1 // The first expression is contextually converted to bool. + // + // FIXME; GCC's vector extension permits the use of a?b:c where the type of + // a is that of a integer vector with the same number of elements and + // size as the vectors of b and c. If one of either b or c is a scalar + // it is implicitly converted to match the type of the vector. + // Otherwise the expression is ill-formed. If both b and c are scalars, + // then b and c are checked and converted to the type of a if possible. + // Unlike the OpenCL ?: operator, the expression is evaluated as + // (a[0] != 0 ? b[0] : c[0], .. , a[n] != 0 ? b[n] : c[n]). if (!Cond.get()->isTypeDependent()) { ExprResult CondRes = CheckCXXBooleanCondition(Cond.get()); if (CondRes.isInvalid()) diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index a44e9243e3c5..28581bad1a7a 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -4241,8 +4241,7 @@ void Sema::diagnoseARCUnbridgedCast(Expr *e) { castType = cast->getTypeAsWritten(); CCK = CCK_OtherCast; } else { - castType = cast->getType(); - CCK = CCK_ImplicitConversion; + llvm_unreachable("Unexpected ImplicitCastExpr"); } ARCConversionTypeClass castACTC = diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index d0f530010a0d..32024cb335dc 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -1209,7 +1209,7 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity, } else { assert((ElemType->isRecordType() || ElemType->isVectorType() || - ElemType->isClkEventT()) && "Unexpected type"); + ElemType->isOpenCLSpecificType()) && "Unexpected type"); // C99 6.7.8p13: // @@ -8296,8 +8296,46 @@ Sema::PerformCopyInitialization(const InitializedEntity &Entity, AllowExplicit); InitializationSequence Seq(*this, Entity, Kind, InitE, TopLevelOfInitList); + // Prevent infinite recursion when performing parameter copy-initialization. + const bool ShouldTrackCopy = + Entity.isParameterKind() && Seq.isConstructorInitialization(); + if (ShouldTrackCopy) { + if (llvm::find(CurrentParameterCopyTypes, Entity.getType()) != + CurrentParameterCopyTypes.end()) { + Seq.SetOverloadFailure( + InitializationSequence::FK_ConstructorOverloadFailed, + OR_No_Viable_Function); + + // Try to give a meaningful diagnostic note for the problematic + // constructor. + const auto LastStep = Seq.step_end() - 1; + assert(LastStep->Kind == + InitializationSequence::SK_ConstructorInitialization); + const FunctionDecl *Function = LastStep->Function.Function; + auto Candidate = + llvm::find_if(Seq.getFailedCandidateSet(), + [Function](const OverloadCandidate &Candidate) -> bool { + return Candidate.Viable && + Candidate.Function == Function && + Candidate.Conversions.size() > 0; + }); + if (Candidate != Seq.getFailedCandidateSet().end() && + Function->getNumParams() > 0) { + Candidate->Viable = false; + Candidate->FailureKind = ovl_fail_bad_conversion; + Candidate->Conversions[0].setBad(BadConversionSequence::no_conversion, + InitE, + Function->getParamDecl(0)->getType()); + } + } + CurrentParameterCopyTypes.push_back(Entity.getType()); + } + ExprResult Result = Seq.Perform(*this, Entity, Kind, InitE); + if (ShouldTrackCopy) + CurrentParameterCopyTypes.pop_back(); + return Result; } diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index ce76e14982db..c5b579a4b2e9 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -1382,8 +1382,8 @@ Module *Sema::getOwningModule(Decl *Entity) { return M; } -void Sema::makeMergedDefinitionVisible(NamedDecl *ND, SourceLocation Loc) { - if (auto *M = PP.getModuleContainingLocation(Loc)) +void Sema::makeMergedDefinitionVisible(NamedDecl *ND) { + if (auto *M = getCurrentModule()) Context.mergeDefinitionIntoModule(ND, M); else // We're not building a module; just make the definition visible. @@ -1393,7 +1393,7 @@ void Sema::makeMergedDefinitionVisible(NamedDecl *ND, SourceLocation Loc) { // visible too. They're not (necessarily) within a mergeable DeclContext. if (auto *TD = dyn_cast(ND)) for (auto *Param : *TD->getTemplateParameters()) - makeMergedDefinitionVisible(Param, Loc); + makeMergedDefinitionVisible(Param); } /// \brief Find the module in which the given declaration was defined. @@ -3445,7 +3445,8 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result, bool QualifiedNameLookup, bool InBaseClass, VisibleDeclConsumer &Consumer, - VisibleDeclsRecord &Visited) { + VisibleDeclsRecord &Visited, + bool IncludeDependentBases = false) { if (!Ctx) return; @@ -3501,7 +3502,8 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result, ShadowContextRAII Shadow(Visited); for (auto I : Ctx->using_directives()) { LookupVisibleDecls(I->getNominatedNamespace(), Result, - QualifiedNameLookup, InBaseClass, Consumer, Visited); + QualifiedNameLookup, InBaseClass, Consumer, Visited, + IncludeDependentBases); } } @@ -3513,14 +3515,28 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result, for (const auto &B : Record->bases()) { QualType BaseType = B.getType(); - // Don't look into dependent bases, because name lookup can't look - // there anyway. - if (BaseType->isDependentType()) - continue; - - const RecordType *Record = BaseType->getAs(); - if (!Record) - continue; + RecordDecl *RD; + if (BaseType->isDependentType()) { + if (!IncludeDependentBases) { + // Don't look into dependent bases, because name lookup can't look + // there anyway. + continue; + } + const auto *TST = BaseType->getAs(); + if (!TST) + continue; + TemplateName TN = TST->getTemplateName(); + const auto *TD = + dyn_cast_or_null(TN.getAsTemplateDecl()); + if (!TD) + continue; + RD = TD->getTemplatedDecl(); + } else { + const auto *Record = BaseType->getAs(); + if (!Record) + continue; + RD = Record->getDecl(); + } // FIXME: It would be nice to be able to determine whether referencing // a particular member would be ambiguous. For example, given @@ -3543,8 +3559,8 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result, // Find results in this base class (and its bases). ShadowContextRAII Shadow(Visited); - LookupVisibleDecls(Record->getDecl(), Result, QualifiedNameLookup, - true, Consumer, Visited); + LookupVisibleDecls(RD, Result, QualifiedNameLookup, true, Consumer, + Visited, IncludeDependentBases); } } @@ -3713,7 +3729,8 @@ void Sema::LookupVisibleDecls(Scope *S, LookupNameKind Kind, void Sema::LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind, VisibleDeclConsumer &Consumer, - bool IncludeGlobalScope) { + bool IncludeGlobalScope, + bool IncludeDependentBases) { LookupResult Result(*this, DeclarationName(), SourceLocation(), Kind); Result.setAllowHidden(Consumer.includeHiddenDecls()); VisibleDeclsRecord Visited; @@ -3721,7 +3738,8 @@ void Sema::LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind, Visited.visitedContext(Context.getTranslationUnitDecl()); ShadowContextRAII Shadow(Visited); ::LookupVisibleDecls(Ctx, Result, /*QualifiedNameLookup=*/true, - /*InBaseClass=*/false, Consumer, Visited); + /*InBaseClass=*/false, Consumer, Visited, + IncludeDependentBases); } /// LookupOrCreateLabel - Do a name lookup of a label with the specified name. diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 782c377e3202..51794160278c 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -11210,12 +11210,12 @@ Sema::resolveAddressOfOnlyViableOverloadCandidate(Expr *E, /// \brief Given an overloaded function, tries to turn it into a non-overloaded /// function reference using resolveAddressOfOnlyViableOverloadCandidate. This /// will perform access checks, diagnose the use of the resultant decl, and, if -/// necessary, perform a function-to-pointer decay. +/// requested, potentially perform a function-to-pointer decay. /// /// Returns false if resolveAddressOfOnlyViableOverloadCandidate fails. /// Otherwise, returns true. This may emit diagnostics and return true. bool Sema::resolveAndFixAddressOfOnlyViableOverloadCandidate( - ExprResult &SrcExpr) { + ExprResult &SrcExpr, bool DoFunctionPointerConverion) { Expr *E = SrcExpr.get(); assert(E->getType() == Context.OverloadTy && "SrcExpr must be an overload"); @@ -11230,7 +11230,7 @@ bool Sema::resolveAndFixAddressOfOnlyViableOverloadCandidate( DiagnoseUseOfDecl(Found, E->getExprLoc()); CheckAddressOfMemberAccess(E, DAP); Expr *Fixed = FixOverloadedFunctionReference(E, DAP, Found); - if (Fixed->getType()->isFunctionType()) + if (DoFunctionPointerConverion && Fixed->getType()->isFunctionType()) SrcExpr = DefaultFunctionArrayConversion(Fixed, /*Diagnose=*/false); else SrcExpr = Fixed; diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 5d7eada28717..33a8f9c4afa3 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -2268,9 +2268,57 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation CoawaitLoc, BoundExpr = IntegerLiteral::Create( Context, CAT->getSize(), Context.getPointerDiffType(), RangeLoc); else if (const VariableArrayType *VAT = - dyn_cast(UnqAT)) - BoundExpr = VAT->getSizeExpr(); - else { + dyn_cast(UnqAT)) { + // For a variably modified type we can't just use the expression within + // the array bounds, since we don't want that to be re-evaluated here. + // Rather, we need to determine what it was when the array was first + // created - so we resort to using sizeof(vla)/sizeof(element). + // For e.g. + // void f(int b) { + // int vla[b]; + // b = -1; <-- This should not affect the num of iterations below + // for (int &c : vla) { .. } + // } + + // FIXME: This results in codegen generating IR that recalculates the + // run-time number of elements (as opposed to just using the IR Value + // that corresponds to the run-time value of each bound that was + // generated when the array was created.) If this proves too embarassing + // even for unoptimized IR, consider passing a magic-value/cookie to + // codegen that then knows to simply use that initial llvm::Value (that + // corresponds to the bound at time of array creation) within + // getelementptr. But be prepared to pay the price of increasing a + // customized form of coupling between the two components - which could + // be hard to maintain as the codebase evolves. + + ExprResult SizeOfVLAExprR = ActOnUnaryExprOrTypeTraitExpr( + EndVar->getLocation(), UETT_SizeOf, + /*isType=*/true, + CreateParsedType(VAT->desugar(), Context.getTrivialTypeSourceInfo( + VAT->desugar(), RangeLoc)) + .getAsOpaquePtr(), + EndVar->getSourceRange()); + if (SizeOfVLAExprR.isInvalid()) + return StmtError(); + + ExprResult SizeOfEachElementExprR = ActOnUnaryExprOrTypeTraitExpr( + EndVar->getLocation(), UETT_SizeOf, + /*isType=*/true, + CreateParsedType(VAT->desugar(), + Context.getTrivialTypeSourceInfo( + VAT->getElementType(), RangeLoc)) + .getAsOpaquePtr(), + EndVar->getSourceRange()); + if (SizeOfEachElementExprR.isInvalid()) + return StmtError(); + + BoundExpr = + ActOnBinOp(S, EndVar->getLocation(), tok::slash, + SizeOfVLAExprR.get(), SizeOfEachElementExprR.get()); + if (BoundExpr.isInvalid()) + return StmtError(); + + } else { // Can't be a DependentSizedArrayType or an IncompleteArrayType since // UnqAT is not incomplete and Range is not type-dependent. llvm_unreachable("Unexpected array type in for-range"); diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 61b4df40964c..a479d1027533 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -455,6 +455,85 @@ void Sema::LookupTemplateName(LookupResult &Found, } } +void Sema::diagnoseExprIntendedAsTemplateName(Scope *S, ExprResult TemplateName, + SourceLocation Less, + SourceLocation Greater) { + if (TemplateName.isInvalid()) + return; + + DeclarationNameInfo NameInfo; + CXXScopeSpec SS; + LookupNameKind LookupKind; + + DeclContext *LookupCtx = nullptr; + NamedDecl *Found = nullptr; + + // Figure out what name we looked up. + if (auto *ME = dyn_cast(TemplateName.get())) { + NameInfo = ME->getMemberNameInfo(); + SS.Adopt(ME->getQualifierLoc()); + LookupKind = LookupMemberName; + LookupCtx = ME->getBase()->getType()->getAsCXXRecordDecl(); + Found = ME->getMemberDecl(); + } else { + auto *DRE = cast(TemplateName.get()); + NameInfo = DRE->getNameInfo(); + SS.Adopt(DRE->getQualifierLoc()); + LookupKind = LookupOrdinaryName; + Found = DRE->getFoundDecl(); + } + + // Try to correct the name by looking for templates and C++ named casts. + struct TemplateCandidateFilter : CorrectionCandidateCallback { + TemplateCandidateFilter() { + WantTypeSpecifiers = false; + WantExpressionKeywords = false; + WantRemainingKeywords = false; + WantCXXNamedCasts = true; + }; + bool ValidateCandidate(const TypoCorrection &Candidate) override { + if (auto *ND = Candidate.getCorrectionDecl()) + return isAcceptableTemplateName(ND->getASTContext(), ND, true); + return Candidate.isKeyword(); + } + }; + + DeclarationName Name = NameInfo.getName(); + if (TypoCorrection Corrected = + CorrectTypo(NameInfo, LookupKind, S, &SS, + llvm::make_unique(), + CTK_ErrorRecovery, LookupCtx)) { + auto *ND = Corrected.getFoundDecl(); + if (ND) + ND = isAcceptableTemplateName(Context, ND, + /*AllowFunctionTemplates*/ true); + if (ND || Corrected.isKeyword()) { + if (LookupCtx) { + std::string CorrectedStr(Corrected.getAsString(getLangOpts())); + bool DroppedSpecifier = Corrected.WillReplaceSpecifier() && + Name.getAsString() == CorrectedStr; + diagnoseTypo(Corrected, + PDiag(diag::err_non_template_in_member_template_id_suggest) + << Name << LookupCtx << DroppedSpecifier + << SS.getRange(), false); + } else { + diagnoseTypo(Corrected, + PDiag(diag::err_non_template_in_template_id_suggest) + << Name, false); + } + if (Found) + Diag(Found->getLocation(), + diag::note_non_template_in_template_id_found); + return; + } + } + + Diag(NameInfo.getLoc(), diag::err_non_template_in_template_id) + << Name << SourceRange(Less, Greater); + if (Found) + Diag(Found->getLocation(), diag::note_non_template_in_template_id_found); +} + /// ActOnDependentIdExpression - Handle a dependent id-expression that /// was just parsed. This is only possible with an explicit scope /// specifier naming a dependent type. @@ -1251,8 +1330,8 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, auto *Tmpl = cast(Hidden)->getDescribedClassTemplate(); assert(Tmpl && "original definition of a class template is not a " "class template?"); - makeMergedDefinitionVisible(Hidden, KWLoc); - makeMergedDefinitionVisible(Tmpl, KWLoc); + makeMergedDefinitionVisible(Hidden); + makeMergedDefinitionVisible(Tmpl); return Def; } @@ -7352,7 +7431,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, NamedDecl *Hidden = nullptr; if (Def && SkipBody && !hasVisibleDefinition(Def, &Hidden)) { SkipBody->ShouldSkip = true; - makeMergedDefinitionVisible(Hidden, KWLoc); + makeMergedDefinitionVisible(Hidden); // From here on out, treat this as just a redeclaration. TUK = TUK_Declaration; } else if (Def) { @@ -7825,6 +7904,9 @@ bool Sema::CheckFunctionTemplateSpecialization( // C++11 [dcl.constexpr]p1: An explicit specialization of a constexpr // function can differ from the template declaration with respect to // the constexpr specifier. + // FIXME: We need an update record for this AST mutation. + // FIXME: What if there are multiple such prior declarations (for instance, + // from different modules)? Specialization->setConstexpr(FD->isConstexpr()); } @@ -7872,9 +7954,11 @@ bool Sema::CheckFunctionTemplateSpecialization( // flag to not-deleted, so that we can inherit that information from 'FD'. if (Specialization->isDeleted() && !SpecInfo->isExplicitSpecialization() && !Specialization->getCanonicalDecl()->isReferenced()) { + // FIXME: This assert will not hold in the presence of modules. assert( Specialization->getCanonicalDecl() == Specialization && "This must be the only existing declaration of this specialization"); + // FIXME: We need an update record for this AST mutation. Specialization->setDeletedAsWritten(false); } SpecInfo->setTemplateSpecializationKind(TSK_ExplicitSpecialization); @@ -7987,8 +8071,11 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) { return false; } - // If this is a friend, just bail out here before we start turning - // things into explicit specializations. + // A member specialization in a friend declaration isn't really declaring + // an explicit specialization, just identifying a specific (possibly implicit) + // specialization. Don't change the template specialization kind. + // + // FIXME: Is this really valid? Other compilers reject. if (Member->getFriendObjectKind() != Decl::FOK_None) { // Preserve instantiation information. if (InstantiatedFrom && isa(Member)) { @@ -8038,66 +8125,36 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) { false)) return true; - // Note that this is an explicit instantiation of a member. - // the original declaration to note that it is an explicit specialization - // (if it was previously an implicit instantiation). This latter step - // makes bookkeeping easier. - if (isa(Member)) { + // Note that this member specialization is an "instantiation of" the + // corresponding member of the original template. + if (auto *MemberFunction = dyn_cast(Member)) { FunctionDecl *InstantiationFunction = cast(Instantiation); if (InstantiationFunction->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) { - InstantiationFunction->setTemplateSpecializationKind( - TSK_ExplicitSpecialization); - InstantiationFunction->setLocation(Member->getLocation()); // Explicit specializations of member functions of class templates do not // inherit '=delete' from the member function they are specializing. if (InstantiationFunction->isDeleted()) { + // FIXME: This assert will not hold in the presence of modules. assert(InstantiationFunction->getCanonicalDecl() == InstantiationFunction); + // FIXME: We need an update record for this AST mutation. InstantiationFunction->setDeletedAsWritten(false); } } - cast(Member)->setInstantiationOfMemberFunction( - cast(InstantiatedFrom), - TSK_ExplicitSpecialization); - MarkUnusedFileScopedDecl(InstantiationFunction); - } else if (isa(Member)) { - VarDecl *InstantiationVar = cast(Instantiation); - if (InstantiationVar->getTemplateSpecializationKind() == - TSK_ImplicitInstantiation) { - InstantiationVar->setTemplateSpecializationKind( - TSK_ExplicitSpecialization); - InstantiationVar->setLocation(Member->getLocation()); - } - - cast(Member)->setInstantiationOfStaticDataMember( + MemberFunction->setInstantiationOfMemberFunction( + cast(InstantiatedFrom), TSK_ExplicitSpecialization); + } else if (auto *MemberVar = dyn_cast(Member)) { + MemberVar->setInstantiationOfStaticDataMember( cast(InstantiatedFrom), TSK_ExplicitSpecialization); - MarkUnusedFileScopedDecl(InstantiationVar); - } else if (isa(Member)) { - CXXRecordDecl *InstantiationClass = cast(Instantiation); - if (InstantiationClass->getTemplateSpecializationKind() == - TSK_ImplicitInstantiation) { - InstantiationClass->setTemplateSpecializationKind( - TSK_ExplicitSpecialization); - InstantiationClass->setLocation(Member->getLocation()); - } - - cast(Member)->setInstantiationOfMemberClass( - cast(InstantiatedFrom), - TSK_ExplicitSpecialization); - } else { - assert(isa(Member) && "Only member enums remain"); - EnumDecl *InstantiationEnum = cast(Instantiation); - if (InstantiationEnum->getTemplateSpecializationKind() == - TSK_ImplicitInstantiation) { - InstantiationEnum->setTemplateSpecializationKind( - TSK_ExplicitSpecialization); - InstantiationEnum->setLocation(Member->getLocation()); - } - - cast(Member)->setInstantiationOfMemberEnum( + } else if (auto *MemberClass = dyn_cast(Member)) { + MemberClass->setInstantiationOfMemberClass( + cast(InstantiatedFrom), TSK_ExplicitSpecialization); + } else if (auto *MemberEnum = dyn_cast(Member)) { + MemberEnum->setInstantiationOfMemberEnum( cast(InstantiatedFrom), TSK_ExplicitSpecialization); + } else { + llvm_unreachable("unknown member specialization kind"); } // Save the caller the trouble of having to figure out which declaration @@ -8107,6 +8164,43 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) { return false; } +/// Complete the explicit specialization of a member of a class template by +/// updating the instantiated member to be marked as an explicit specialization. +/// +/// \param OrigD The member declaration instantiated from the template. +/// \param Loc The location of the explicit specialization of the member. +template +static void completeMemberSpecializationImpl(Sema &S, DeclT *OrigD, + SourceLocation Loc) { + if (OrigD->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) + return; + + // FIXME: Inform AST mutation listeners of this AST mutation. + // FIXME: If there are multiple in-class declarations of the member (from + // multiple modules, or a declaration and later definition of a member type), + // should we update all of them? + OrigD->setTemplateSpecializationKind(TSK_ExplicitSpecialization); + OrigD->setLocation(Loc); +} + +void Sema::CompleteMemberSpecialization(NamedDecl *Member, + LookupResult &Previous) { + NamedDecl *Instantiation = cast(Member->getCanonicalDecl()); + if (Instantiation == Member) + return; + + if (auto *Function = dyn_cast(Instantiation)) + completeMemberSpecializationImpl(*this, Function, Member->getLocation()); + else if (auto *Var = dyn_cast(Instantiation)) + completeMemberSpecializationImpl(*this, Var, Member->getLocation()); + else if (auto *Record = dyn_cast(Instantiation)) + completeMemberSpecializationImpl(*this, Record, Member->getLocation()); + else if (auto *Enum = dyn_cast(Instantiation)) + completeMemberSpecializationImpl(*this, Enum, Member->getLocation()); + else + llvm_unreachable("unknown member specialization kind"); +} + /// \brief Check the scope of an explicit instantiation. /// /// \returns true if a serious error occurs, false otherwise. diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 9a71a17561c7..03df6fde6c80 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1849,6 +1849,19 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, } } } + + // Check the template parameter list against the previous declaration. The + // goal here is to pick up default arguments added since the friend was + // declared; we know the template parameter lists match, since otherwise + // we would not have picked this template as the previous declaration. + if (TemplateParams && FunctionTemplate->getPreviousDecl()) { + SemaRef.CheckTemplateParameterList( + TemplateParams, + FunctionTemplate->getPreviousDecl()->getTemplateParameters(), + Function->isThisDeclarationADefinition() + ? Sema::TPC_FriendFunctionTemplateDefinition + : Sema::TPC_FriendFunctionTemplate); + } } if (Function->isLocalExternDecl() && !Function->getPreviousDecl()) @@ -3660,6 +3673,7 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New, New->setType(SemaRef.Context.getFunctionType( NewProto->getReturnType(), NewProto->getParamTypes(), EPI)); } else { + Sema::ContextRAII SwitchContext(SemaRef, New); SemaRef.SubstExceptionSpec(New, Proto, TemplateArgs); } } diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index bcc66bbd1c0a..3992179fabae 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -2285,8 +2285,9 @@ bool Sema::CheckFunctionReturnType(QualType T, SourceLocation Loc) { // Methods cannot return interface types. All ObjC objects are // passed by reference. if (T->isObjCObjectType()) { - Diag(Loc, diag::err_object_cannot_be_passed_returned_by_value) << 0 << T; - return 0; + Diag(Loc, diag::err_object_cannot_be_passed_returned_by_value) + << 0 << T << FixItHint::CreateInsertion(Loc, "*"); + return true; } return false; diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 61b5a822c552..ef8481488302 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -1534,9 +1534,8 @@ MacroInfo *ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset) { return Macro; unsigned NextIndex = 1; // Skip identifier ID. - SubmoduleID SubModID = getGlobalSubmoduleID(F, Record[NextIndex++]); SourceLocation Loc = ReadSourceLocation(F, Record, NextIndex); - MacroInfo *MI = PP.AllocateDeserializedMacroInfo(Loc, SubModID); + MacroInfo *MI = PP.AllocateMacroInfo(Loc); MI->setDefinitionEndLoc(ReadSourceLocation(F, Record, NextIndex)); MI->setIsUsed(Record[NextIndex++]); MI->setUsedForHeaderGuard(Record[NextIndex++]); diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 8e4b217a44cd..b6c0cb2815fb 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -2413,7 +2413,6 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) { } AddIdentifierRef(Name, Record); - Record.push_back(inferSubmoduleIDFromLocation(MI->getDefinitionLoc())); AddSourceLocation(MI->getDefinitionLoc(), Record); AddSourceLocation(MI->getDefinitionEndLoc(), Record); Record.push_back(MI->isUsed()); diff --git a/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp b/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp index 1ea85d60c9e9..371187747f03 100644 --- a/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp +++ b/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp @@ -233,19 +233,16 @@ void NilArgChecker::checkPreObjCMessage(const ObjCMethodCall &msg, if (StringSelectors.empty()) { ASTContext &Ctx = C.getASTContext(); Selector Sels[] = { - getKeywordSelector(Ctx, "caseInsensitiveCompare", nullptr), - getKeywordSelector(Ctx, "compare", nullptr), - getKeywordSelector(Ctx, "compare", "options", nullptr), - getKeywordSelector(Ctx, "compare", "options", "range", nullptr), - getKeywordSelector(Ctx, "compare", "options", "range", "locale", - nullptr), - getKeywordSelector(Ctx, "componentsSeparatedByCharactersInSet", - nullptr), - getKeywordSelector(Ctx, "initWithFormat", - nullptr), - getKeywordSelector(Ctx, "localizedCaseInsensitiveCompare", nullptr), - getKeywordSelector(Ctx, "localizedCompare", nullptr), - getKeywordSelector(Ctx, "localizedStandardCompare", nullptr), + getKeywordSelector(Ctx, "caseInsensitiveCompare"), + getKeywordSelector(Ctx, "compare"), + getKeywordSelector(Ctx, "compare", "options"), + getKeywordSelector(Ctx, "compare", "options", "range"), + getKeywordSelector(Ctx, "compare", "options", "range", "locale"), + getKeywordSelector(Ctx, "componentsSeparatedByCharactersInSet"), + getKeywordSelector(Ctx, "initWithFormat"), + getKeywordSelector(Ctx, "localizedCaseInsensitiveCompare"), + getKeywordSelector(Ctx, "localizedCompare"), + getKeywordSelector(Ctx, "localizedStandardCompare"), }; for (Selector KnownSel : Sels) StringSelectors[KnownSel] = 0; @@ -262,16 +259,15 @@ void NilArgChecker::checkPreObjCMessage(const ObjCMethodCall &msg, if (ArrayWithObjectSel.isNull()) { ASTContext &Ctx = C.getASTContext(); - ArrayWithObjectSel = getKeywordSelector(Ctx, "arrayWithObject", nullptr); - AddObjectSel = getKeywordSelector(Ctx, "addObject", nullptr); + ArrayWithObjectSel = getKeywordSelector(Ctx, "arrayWithObject"); + AddObjectSel = getKeywordSelector(Ctx, "addObject"); InsertObjectAtIndexSel = - getKeywordSelector(Ctx, "insertObject", "atIndex", nullptr); + getKeywordSelector(Ctx, "insertObject", "atIndex"); ReplaceObjectAtIndexWithObjectSel = - getKeywordSelector(Ctx, "replaceObjectAtIndex", "withObject", nullptr); + getKeywordSelector(Ctx, "replaceObjectAtIndex", "withObject"); SetObjectAtIndexedSubscriptSel = - getKeywordSelector(Ctx, "setObject", "atIndexedSubscript", nullptr); - ArrayByAddingObjectSel = - getKeywordSelector(Ctx, "arrayByAddingObject", nullptr); + getKeywordSelector(Ctx, "setObject", "atIndexedSubscript"); + ArrayByAddingObjectSel = getKeywordSelector(Ctx, "arrayByAddingObject"); } if (S == ArrayWithObjectSel || S == AddObjectSel || @@ -292,13 +288,11 @@ void NilArgChecker::checkPreObjCMessage(const ObjCMethodCall &msg, if (DictionaryWithObjectForKeySel.isNull()) { ASTContext &Ctx = C.getASTContext(); DictionaryWithObjectForKeySel = - getKeywordSelector(Ctx, "dictionaryWithObject", "forKey", nullptr); - SetObjectForKeySel = - getKeywordSelector(Ctx, "setObject", "forKey", nullptr); + getKeywordSelector(Ctx, "dictionaryWithObject", "forKey"); + SetObjectForKeySel = getKeywordSelector(Ctx, "setObject", "forKey"); SetObjectForKeyedSubscriptSel = - getKeywordSelector(Ctx, "setObject", "forKeyedSubscript", nullptr); - RemoveObjectForKeySel = - getKeywordSelector(Ctx, "removeObjectForKey", nullptr); + getKeywordSelector(Ctx, "setObject", "forKeyedSubscript"); + RemoveObjectForKeySel = getKeywordSelector(Ctx, "removeObjectForKey"); } if (S == DictionaryWithObjectForKeySel || S == SetObjectForKeySel) { diff --git a/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp b/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp index 8c2aef21b3ca..48d6cd8a527c 100644 --- a/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp @@ -41,6 +41,22 @@ bool BuiltinFunctionChecker::evalCall(const CallExpr *CE, default: return false; + case Builtin::BI__builtin_assume: { + assert (CE->arg_begin() != CE->arg_end()); + SVal ArgSVal = state->getSVal(CE->getArg(0), LCtx); + if (ArgSVal.isUndef()) + return true; // Return true to model purity. + + state = state->assume(ArgSVal.castAs(), true); + // FIXME: do we want to warn here? Not right now. The most reports might + // come from infeasible paths, thus being false positives. + if (!state) + return true; + + C.addTransition(state); + return true; + } + case Builtin::BI__builtin_unpredictable: case Builtin::BI__builtin_expect: case Builtin::BI__builtin_assume_aligned: diff --git a/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp b/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp index c1deadef4202..8a5c769b6b50 100644 --- a/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp @@ -123,14 +123,14 @@ void NoReturnFunctionChecker::checkPostObjCMessage(const ObjCMethodCall &Msg, case 4: lazyInitKeywordSelector(HandleFailureInFunctionSel, C.getASTContext(), "handleFailureInFunction", "file", "lineNumber", - "description", nullptr); + "description"); if (Sel != HandleFailureInFunctionSel) return; break; case 5: lazyInitKeywordSelector(HandleFailureInMethodSel, C.getASTContext(), "handleFailureInMethod", "object", "file", - "lineNumber", "description", nullptr); + "lineNumber", "description"); if (Sel != HandleFailureInMethodSel) return; break; diff --git a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp index 3f6ae6222ce0..89b1291c4f46 100644 --- a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp @@ -703,31 +703,30 @@ class RetainSummaryManager { ObjCMethodSummaries[ObjCSummaryKey(ClsII, S)] = Summ; } + template void addMethodSummary(IdentifierInfo *ClsII, ObjCMethodSummariesTy &Summaries, - const RetainSummary *Summ, va_list argp) { - Selector S = getKeywordSelector(Ctx, argp); + const RetainSummary *Summ, Keywords *... Kws) { + Selector S = getKeywordSelector(Ctx, Kws...); Summaries[ObjCSummaryKey(ClsII, S)] = Summ; } - void addInstMethSummary(const char* Cls, const RetainSummary * Summ, ...) { - va_list argp; - va_start(argp, Summ); - addMethodSummary(&Ctx.Idents.get(Cls), ObjCMethodSummaries, Summ, argp); - va_end(argp); + template + void addInstMethSummary(const char *Cls, const RetainSummary *Summ, + Keywords *... Kws) { + addMethodSummary(&Ctx.Idents.get(Cls), ObjCMethodSummaries, Summ, Kws...); } - void addClsMethSummary(const char* Cls, const RetainSummary * Summ, ...) { - va_list argp; - va_start(argp, Summ); - addMethodSummary(&Ctx.Idents.get(Cls),ObjCClassMethodSummaries, Summ, argp); - va_end(argp); + template + void addClsMethSummary(const char *Cls, const RetainSummary *Summ, + Keywords *... Kws) { + addMethodSummary(&Ctx.Idents.get(Cls), ObjCClassMethodSummaries, Summ, + Kws...); } - void addClsMethSummary(IdentifierInfo *II, const RetainSummary * Summ, ...) { - va_list argp; - va_start(argp, Summ); - addMethodSummary(II, ObjCClassMethodSummaries, Summ, argp); - va_end(argp); + template + void addClsMethSummary(IdentifierInfo *II, const RetainSummary *Summ, + Keywords *... Kws) { + addMethodSummary(II, ObjCClassMethodSummaries, Summ, Kws...); } public: @@ -1640,20 +1639,16 @@ void RetainSummaryManager::InitializeMethodSummaries() { addClassMethSummary("NSAutoreleasePool", "new", NoTrackYet); // Create summaries QCRenderer/QCView -createSnapShotImageOfType: - addInstMethSummary("QCRenderer", AllocSumm, - "createSnapshotImageOfType", nullptr); - addInstMethSummary("QCView", AllocSumm, - "createSnapshotImageOfType", nullptr); + addInstMethSummary("QCRenderer", AllocSumm, "createSnapshotImageOfType"); + addInstMethSummary("QCView", AllocSumm, "createSnapshotImageOfType"); // Create summaries for CIContext, 'createCGImage' and // 'createCGLayerWithSize'. These objects are CF objects, and are not // automatically garbage collected. - addInstMethSummary("CIContext", CFAllocSumm, - "createCGImage", "fromRect", nullptr); + addInstMethSummary("CIContext", CFAllocSumm, "createCGImage", "fromRect"); addInstMethSummary("CIContext", CFAllocSumm, "createCGImage", "fromRect", - "format", "colorSpace", nullptr); - addInstMethSummary("CIContext", CFAllocSumm, "createCGLayerWithSize", "info", - nullptr); + "format", "colorSpace"); + addInstMethSummary("CIContext", CFAllocSumm, "createCGLayerWithSize", "info"); } //===----------------------------------------------------------------------===// diff --git a/lib/StaticAnalyzer/Checkers/SelectorExtras.h b/lib/StaticAnalyzer/Checkers/SelectorExtras.h index 41f70d7d5b69..b11d070c629b 100644 --- a/lib/StaticAnalyzer/Checkers/SelectorExtras.h +++ b/lib/StaticAnalyzer/Checkers/SelectorExtras.h @@ -11,48 +11,26 @@ #define LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_SELECTOREXTRAS_H #include "clang/AST/ASTContext.h" -#include namespace clang { namespace ento { -static inline Selector getKeywordSelectorImpl(ASTContext &Ctx, - const char *First, - va_list argp) { - SmallVector II; - II.push_back(&Ctx.Idents.get(First)); - - while (const char *s = va_arg(argp, const char *)) - II.push_back(&Ctx.Idents.get(s)); +template +static inline Selector getKeywordSelector(ASTContext &Ctx, + IdentifierInfos *... IIs) { + static_assert(sizeof...(IdentifierInfos), + "keyword selectors must have at least one argument"); + SmallVector II({&Ctx.Idents.get(IIs)...}); return Ctx.Selectors.getSelector(II.size(), &II[0]); } -static inline Selector getKeywordSelector(ASTContext &Ctx, va_list argp) { - const char *First = va_arg(argp, const char *); - assert(First && "keyword selectors must have at least one argument"); - return getKeywordSelectorImpl(Ctx, First, argp); -} - -LLVM_END_WITH_NULL -static inline Selector getKeywordSelector(ASTContext &Ctx, - const char *First, ...) { - va_list argp; - va_start(argp, First); - Selector result = getKeywordSelectorImpl(Ctx, First, argp); - va_end(argp); - return result; -} - -LLVM_END_WITH_NULL +template static inline void lazyInitKeywordSelector(Selector &Sel, ASTContext &Ctx, - const char *First, ...) { + IdentifierInfos *... IIs) { if (!Sel.isNull()) return; - va_list argp; - va_start(argp, First); - Sel = getKeywordSelectorImpl(Ctx, First, argp); - va_end(argp); + Sel = getKeywordSelector(Ctx, IIs...); } static inline void lazyInitNullarySelector(Selector &Sel, ASTContext &Ctx, diff --git a/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp b/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp index 93ad17cffb34..2f9f5d2d9cf8 100644 --- a/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp @@ -440,7 +440,10 @@ StdLibraryFunctionsChecker::findFunctionSummary(const FunctionDecl *FD, BasicValueFactory &BVF = SVB.getBasicValueFactory(); initFunctionSummaries(BVF); - std::string Name = FD->getQualifiedNameAsString(); + IdentifierInfo *II = FD->getIdentifier(); + if (!II) + return None; + StringRef Name = II->getName(); if (Name.empty() || !C.isCLibraryFunction(FD, Name)) return None; diff --git a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp index 39d88bfda148..caf86b26b66d 100644 --- a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp @@ -447,6 +447,7 @@ bool ExprEngine::inlineCall(const CallEvent &Call, const Decl *D, Bldr.takeNodes(Pred); NumInlinedCalls++; + Engine.FunctionSummaries->bumpNumTimesInlined(D); // Mark the decl as visited. if (VisitedCallees) @@ -868,8 +869,6 @@ bool ExprEngine::shouldInlineCall(const CallEvent &Call, const Decl *D, || IsRecursive)) return false; - Engine.FunctionSummaries->bumpNumTimesInlined(D); - return true; } diff --git a/lib/Tooling/RefactoringCallbacks.cpp b/lib/Tooling/RefactoringCallbacks.cpp index e900c23e4f64..9fd333ca554e 100644 --- a/lib/Tooling/RefactoringCallbacks.cpp +++ b/lib/Tooling/RefactoringCallbacks.cpp @@ -9,8 +9,13 @@ // // //===----------------------------------------------------------------------===// -#include "clang/Lex/Lexer.h" #include "clang/Tooling/RefactoringCallbacks.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Lex/Lexer.h" + +using llvm::StringError; +using llvm::make_error; namespace clang { namespace tooling { @@ -20,18 +25,62 @@ tooling::Replacements &RefactoringCallback::getReplacements() { return Replace; } -static Replacement replaceStmtWithText(SourceManager &Sources, - const Stmt &From, - StringRef Text) { - return tooling::Replacement(Sources, CharSourceRange::getTokenRange( - From.getSourceRange()), Text); +ASTMatchRefactorer::ASTMatchRefactorer( + std::map &FileToReplaces) + : FileToReplaces(FileToReplaces) {} + +void ASTMatchRefactorer::addDynamicMatcher( + const ast_matchers::internal::DynTypedMatcher &Matcher, + RefactoringCallback *Callback) { + MatchFinder.addDynamicMatcher(Matcher, Callback); + Callbacks.push_back(Callback); } -static Replacement replaceStmtWithStmt(SourceManager &Sources, - const Stmt &From, + +class RefactoringASTConsumer : public ASTConsumer { +public: + explicit RefactoringASTConsumer(ASTMatchRefactorer &Refactoring) + : Refactoring(Refactoring) {} + + void HandleTranslationUnit(ASTContext &Context) override { + // The ASTMatchRefactorer is re-used between translation units. + // Clear the matchers so that each Replacement is only emitted once. + for (const auto &Callback : Refactoring.Callbacks) { + Callback->getReplacements().clear(); + } + Refactoring.MatchFinder.matchAST(Context); + for (const auto &Callback : Refactoring.Callbacks) { + for (const auto &Replacement : Callback->getReplacements()) { + llvm::Error Err = + Refactoring.FileToReplaces[Replacement.getFilePath()].add( + Replacement); + if (Err) { + llvm::errs() << "Skipping replacement " << Replacement.toString() + << " due to this error:\n" + << toString(std::move(Err)) << "\n"; + } + } + } + } + +private: + ASTMatchRefactorer &Refactoring; +}; + +std::unique_ptr ASTMatchRefactorer::newASTConsumer() { + return llvm::make_unique(*this); +} + +static Replacement replaceStmtWithText(SourceManager &Sources, const Stmt &From, + StringRef Text) { + return tooling::Replacement( + Sources, CharSourceRange::getTokenRange(From.getSourceRange()), Text); +} +static Replacement replaceStmtWithStmt(SourceManager &Sources, const Stmt &From, const Stmt &To) { - return replaceStmtWithText(Sources, From, Lexer::getSourceText( - CharSourceRange::getTokenRange(To.getSourceRange()), - Sources, LangOptions())); + return replaceStmtWithText( + Sources, From, + Lexer::getSourceText(CharSourceRange::getTokenRange(To.getSourceRange()), + Sources, LangOptions())); } ReplaceStmtWithText::ReplaceStmtWithText(StringRef FromId, StringRef ToText) @@ -103,5 +152,90 @@ void ReplaceIfStmtWithItsBody::run( } } +ReplaceNodeWithTemplate::ReplaceNodeWithTemplate( + llvm::StringRef FromId, std::vector Template) + : FromId(FromId), Template(std::move(Template)) {} + +llvm::Expected> +ReplaceNodeWithTemplate::create(StringRef FromId, StringRef ToTemplate) { + std::vector ParsedTemplate; + for (size_t Index = 0; Index < ToTemplate.size();) { + if (ToTemplate[Index] == '$') { + if (ToTemplate.substr(Index, 2) == "$$") { + Index += 2; + ParsedTemplate.push_back( + TemplateElement{TemplateElement::Literal, "$"}); + } else if (ToTemplate.substr(Index, 2) == "${") { + size_t EndOfIdentifier = ToTemplate.find("}", Index); + if (EndOfIdentifier == std::string::npos) { + return make_error( + "Unterminated ${...} in replacement template near " + + ToTemplate.substr(Index), + llvm::inconvertibleErrorCode()); + } + std::string SourceNodeName = + ToTemplate.substr(Index + 2, EndOfIdentifier - Index - 2); + ParsedTemplate.push_back( + TemplateElement{TemplateElement::Identifier, SourceNodeName}); + Index = EndOfIdentifier + 1; + } else { + return make_error( + "Invalid $ in replacement template near " + + ToTemplate.substr(Index), + llvm::inconvertibleErrorCode()); + } + } else { + size_t NextIndex = ToTemplate.find('$', Index + 1); + ParsedTemplate.push_back( + TemplateElement{TemplateElement::Literal, + ToTemplate.substr(Index, NextIndex - Index)}); + Index = NextIndex; + } + } + return std::unique_ptr( + new ReplaceNodeWithTemplate(FromId, std::move(ParsedTemplate))); +} + +void ReplaceNodeWithTemplate::run( + const ast_matchers::MatchFinder::MatchResult &Result) { + const auto &NodeMap = Result.Nodes.getMap(); + + std::string ToText; + for (const auto &Element : Template) { + switch (Element.Type) { + case TemplateElement::Literal: + ToText += Element.Value; + break; + case TemplateElement::Identifier: { + auto NodeIter = NodeMap.find(Element.Value); + if (NodeIter == NodeMap.end()) { + llvm::errs() << "Node " << Element.Value + << " used in replacement template not bound in Matcher \n"; + llvm::report_fatal_error("Unbound node in replacement template."); + } + CharSourceRange Source = + CharSourceRange::getTokenRange(NodeIter->second.getSourceRange()); + ToText += Lexer::getSourceText(Source, *Result.SourceManager, + Result.Context->getLangOpts()); + break; + } + } + } + if (NodeMap.count(FromId) == 0) { + llvm::errs() << "Node to be replaced " << FromId + << " not bound in query.\n"; + llvm::report_fatal_error("FromId node not bound in MatchResult"); + } + auto Replacement = + tooling::Replacement(*Result.SourceManager, &NodeMap.at(FromId), ToText, + Result.Context->getLangOpts()); + llvm::Error Err = Replace.add(Replacement); + if (Err) { + llvm::errs() << "Query and replace failed in " << Replacement.getFilePath() + << "! " << llvm::toString(std::move(Err)) << "\n"; + llvm::report_fatal_error("Replacement failed"); + } +} + } // end namespace tooling } // end namespace clang diff --git a/test/Analysis/builtin-assume.c b/test/Analysis/builtin-assume.c new file mode 100644 index 000000000000..00d651d9e3be --- /dev/null +++ b/test/Analysis/builtin-assume.c @@ -0,0 +1,8 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify %s + +void clang_analyzer_eval(int); + +void f(int i) { + __builtin_assume(i < 10); + clang_analyzer_eval(i < 15); // expected-warning {{TRUE}} +} diff --git a/test/CXX/drs/dr20xx.cpp b/test/CXX/drs/dr20xx.cpp new file mode 100644 index 000000000000..b97a9a46bc85 --- /dev/null +++ b/test/CXX/drs/dr20xx.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors \ +// RUN: -Wno-variadic-macros -Wno-c11-extensions +// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++1z -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors + +// expected-no-diagnostics + +#if __cplusplus < 201103L +#define static_assert(...) _Static_assert(__VA_ARGS__) +#endif + +namespace dr2094 { // dr2094: 5.0 + struct A { int n; }; + struct B { volatile int n; }; + static_assert(__is_trivially_copyable(volatile int), ""); + static_assert(__is_trivially_copyable(const volatile int), ""); + static_assert(__is_trivially_copyable(const volatile int[]), ""); + static_assert(__is_trivially_copyable(A), ""); + static_assert(__is_trivially_copyable(volatile A), ""); + static_assert(__is_trivially_copyable(const volatile A), ""); + static_assert(__is_trivially_copyable(const volatile A[]), ""); + static_assert(__is_trivially_copyable(B), ""); + + static_assert(__is_trivially_constructible(A, A const&), ""); + static_assert(__is_trivially_constructible(B, B const&), ""); + + static_assert(__is_trivially_assignable(A, const A&), ""); + static_assert(__is_trivially_assignable(B, const B&), ""); +} diff --git a/test/CXX/drs/dr4xx.cpp b/test/CXX/drs/dr4xx.cpp index 3ea226a745f6..a55bb91be558 100644 --- a/test/CXX/drs/dr4xx.cpp +++ b/test/CXX/drs/dr4xx.cpp @@ -1202,16 +1202,15 @@ namespace dr495 { // dr495: 3.5 long n2 = s2; } -namespace dr496 { // dr496: no +namespace dr496 { // dr496: sup dr2094 struct A { int n; }; struct B { volatile int n; }; int check1[ __is_trivially_copyable(const int) ? 1 : -1]; - int check2[!__is_trivially_copyable(volatile int) ? 1 : -1]; + // This checks the dr2094 behavior, not dr496 + int check2[ __is_trivially_copyable(volatile int) ? 1 : -1]; int check3[ __is_trivially_constructible(A, const A&) ? 1 : -1]; - // FIXME: This is wrong. int check4[ __is_trivially_constructible(B, const B&) ? 1 : -1]; int check5[ __is_trivially_assignable(A, const A&) ? 1 : -1]; - // FIXME: This is wrong. int check6[ __is_trivially_assignable(B, const B&) ? 1 : -1]; } diff --git a/test/CodeCompletion/member-access.cpp b/test/CodeCompletion/member-access.cpp index 66872272ee6d..53af121951bb 100644 --- a/test/CodeCompletion/member-access.cpp +++ b/test/CodeCompletion/member-access.cpp @@ -66,3 +66,83 @@ struct Bar { // Make sure this also doesn't crash // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:47:14 %s + + +template +class BaseTemplate { +public: + T baseTemplateFunction(); + + T baseTemplateField; +}; + +template +class TemplateClass: public Base1 , public BaseTemplate { +public: + T function() { } + T field; + + void overload1(const T &); + void overload1(const S &); +}; + +template +void completeDependentMembers(TemplateClass &object, + TemplateClass *object2) { + object.field; + object2->field; +// CHECK-CC2: baseTemplateField : [#T#][#BaseTemplate::#]baseTemplateField +// CHECK-CC2: baseTemplateFunction : [#T#][#BaseTemplate::#]baseTemplateFunction() +// CHECK-CC2: field : [#T#]field +// CHECK-CC2: function : [#T#]function() +// CHECK-CC2: member1 : [#int#][#Base1::#]member1 +// CHECK-CC2: member2 : [#float#][#Base1::#]member2 +// CHECK-CC2: overload1 : [#void#]overload1(<#const T &#>) +// CHECK-CC2: overload1 : [#void#]overload1(<#const S &#>) + +// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:92:10 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s +// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:93:12 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s +} + + +void completeDependentSpecializedMembers(TemplateClass &object, + TemplateClass *object2) { + object.field; + object2->field; +// CHECK-CC3: baseTemplateField : [#int#][#BaseTemplate::#]baseTemplateField +// CHECK-CC3: baseTemplateFunction : [#int#][#BaseTemplate::#]baseTemplateFunction() +// CHECK-CC3: field : [#int#]field +// CHECK-CC3: function : [#int#]function() +// CHECK-CC3: member1 : [#int#][#Base1::#]member1 +// CHECK-CC3: member2 : [#float#][#Base1::#]member2 +// CHECK-CC3: overload1 : [#void#]overload1(<#const int &#>) +// CHECK-CC3: overload1 : [#void#]overload1(<#const double &#>) + +// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:110:10 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s +// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:111:12 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s +} + +template +class Template { +public: + BaseTemplate o1; + BaseTemplate o2; + + void function() { + o1.baseTemplateField; +// CHECK-CC4: BaseTemplate : BaseTemplate:: +// CHECK-CC4: baseTemplateField : [#int#]baseTemplateField +// CHECK-CC4: baseTemplateFunction : [#int#]baseTemplateFunction() +// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:132:8 %s -o - | FileCheck -check-prefix=CHECK-CC4 %s + o2.baseTemplateField; +// CHECK-CC5: BaseTemplate : BaseTemplate:: +// CHECK-CC5: baseTemplateField : [#T#]baseTemplateField +// CHECK-CC5: baseTemplateFunction : [#T#]baseTemplateFunction() +// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:137:8 %s -o - | FileCheck -check-prefix=CHECK-CC5 %s + this->o1; +// CHECK-CC6: [#void#]function() +// CHECK-CC6: o1 : [#BaseTemplate#]o1 +// CHECK-CC6: o2 : [#BaseTemplate#]o2 +// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:142:11 %s -o - | FileCheck -check-prefix=CHECK-CC6 %s + } +}; diff --git a/test/CodeGen/asan-globals-gc.cpp b/test/CodeGen/asan-globals-gc.cpp index 6d64f41dda8d..58ce5f067563 100644 --- a/test/CodeGen/asan-globals-gc.cpp +++ b/test/CodeGen/asan-globals-gc.cpp @@ -1,5 +1,16 @@ -// RUN: %clang_cc1 -fsanitize=address -emit-llvm -o - -triple x86_64-windows-msvc %s | FileCheck %s --check-prefix=WITH-GC -// RUN: %clang_cc1 -fsanitize=address -emit-llvm -o - -triple x86_64-windows-msvc -fdata-sections %s | FileCheck %s --check-prefix=WITH-GC +// RUN: %clang_cc1 -fsanitize=address -fsanitize-address-globals-dead-stripping -emit-llvm -o - -triple x86_64-linux %s | FileCheck %s --check-prefix=WITHOUT-GC +// RUN: %clang_cc1 -fsanitize=address -fsanitize-address-globals-dead-stripping -fdata-sections -emit-llvm -o - -triple x86_64-linux %s | FileCheck %s --check-prefix=WITH-GC +// RUN: %clang_cc1 -fsanitize=address -fsanitize-address-globals-dead-stripping -fno-integrated-as -fdata-sections -emit-llvm -o - -triple x86_64-linux %s | FileCheck %s --check-prefix=WITHOUT-GC +// RUN: %clang_cc1 -fsanitize=address -fsanitize-address-globals-dead-stripping -fno-integrated-as -emit-llvm -o - -triple x86_64-linux %s | FileCheck %s --check-prefix=WITHOUT-GC +// RUN: %clang_cc1 -fsanitize=address -fdata-sections -emit-llvm -o - -triple x86_64-linux %s | FileCheck %s --check-prefix=WITHOUT-GC + +// RUN: %clang_cc1 -fsanitize=address -fsanitize-address-globals-dead-stripping -fno-data-sections -emit-llvm -o - -triple x86_64-windows-msvc %s | FileCheck %s --check-prefix=WITH-GC +// RUN: %clang_cc1 -fsanitize=address -fsanitize-address-globals-dead-stripping -fdata-sections -emit-llvm -o - -triple x86_64-windows-msvc %s | FileCheck %s --check-prefix=WITH-GC +// RUN: %clang_cc1 -fsanitize=address -fdata-sections -emit-llvm -o - -triple x86_64-windows-msvc %s | FileCheck %s --check-prefix=WITHOUT-GC + +// RUN: %clang_cc1 -fsanitize=address -fsanitize-address-globals-dead-stripping -fno-data-sections -emit-llvm -o - -triple x86_64-apple-macosx11 %s | FileCheck %s --check-prefix=WITH-GC +// RUN: %clang_cc1 -fsanitize=address -fsanitize-address-globals-dead-stripping -fdata-sections -emit-llvm -o - -triple x86_64-apple-macosx11 %s | FileCheck %s --check-prefix=WITH-GC +// RUN: %clang_cc1 -fsanitize=address -fdata-sections -emit-llvm -o - -triple x86_64-apple-macosx11 %s | FileCheck %s --check-prefix=WITHOUT-GC int global; diff --git a/test/CodeGen/asan-no-globals-no-comdat.cpp b/test/CodeGen/asan-no-globals-no-comdat.cpp new file mode 100644 index 000000000000..4637346f9c41 --- /dev/null +++ b/test/CodeGen/asan-no-globals-no-comdat.cpp @@ -0,0 +1,11 @@ +// Test that on Linux asan constructor is placed in a comdat iff globals-gc is on. +// Even if there are no globals in the module. + +// RUN: %clang_cc1 -fsanitize=address -fsanitize-address-globals-dead-stripping -emit-llvm -o - -triple x86_64-linux %s | FileCheck %s --check-prefix=WITHOUT-GC +// RUN: %clang_cc1 -fsanitize=address -fsanitize-address-globals-dead-stripping -fdata-sections -emit-llvm -o - -triple x86_64-linux %s | FileCheck %s --check-prefix=WITH-GC +// RUN: %clang_cc1 -fsanitize=address -fsanitize-address-globals-dead-stripping -fno-integrated-as -fdata-sections -emit-llvm -o - -triple x86_64-linux %s | FileCheck %s --check-prefix=WITHOUT-GC +// RUN: %clang_cc1 -fsanitize=address -fsanitize-address-globals-dead-stripping -fno-integrated-as -emit-llvm -o - -triple x86_64-linux %s | FileCheck %s --check-prefix=WITHOUT-GC +// RUN: %clang_cc1 -fsanitize=address -fdata-sections -emit-llvm -o - -triple x86_64-linux %s | FileCheck %s --check-prefix=WITHOUT-GC + +// WITH-GC: define internal void @asan.module_ctor() comdat { +// WITHOUT-GC: define internal void @asan.module_ctor() { diff --git a/test/CodeGen/mips-aggregate-arg.c b/test/CodeGen/mips-aggregate-arg.c new file mode 100644 index 000000000000..ccf30df7c22a --- /dev/null +++ b/test/CodeGen/mips-aggregate-arg.c @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -triple mipsel-unknown-linux-gnu -S -emit-llvm -o - %s | FileCheck -check-prefix=O32 %s +// RUN: %clang_cc1 -triple mips64el-unknown-linux-gnu -S -emit-llvm -o - %s -target-abi n32 | FileCheck -check-prefix=N32-N64 %s +// RUN: %clang_cc1 -triple mips64el-unknown-linux-gnu -S -emit-llvm -o - %s -target-abi n64 | FileCheck -check-prefix=N32-N64 %s + +struct t1 { + char t1[10]; +}; + +struct t2 { + char t2[20]; +}; + +struct t3 { + char t3[65]; +}; + +extern struct t1 g1; +extern struct t2 g2; +extern struct t3 g3; +extern void f1(struct t1); +extern void f2(struct t2); +extern void f3(struct t3); + +void f() { + +// O32: call void @f1(i32 inreg %{{[0-9]+}}, i32 inreg %{{[0-9]+}}, i16 inreg %{{[0-9]+}}) +// O32: call void @f2(%struct.t2* byval align 4 %{{.*}}) +// O32: call void @f3(%struct.t3* byval align 4 %{{.*}}) + +// N32-N64: call void @f1(i64 inreg %{{[0-9]+}}, i16 inreg %{{[0-9]+}}) +// N32-N64: call void @f2(i64 inreg %{{[0-9]+}}, i64 inreg %{{[0-9]+}}, i32 inreg %{{[0-9]+}}) +// N32-N64: call void @f3(%struct.t3* byval align 8 %{{.*}}) + + f1(g1); + f2(g2); + f3(g3); +} + diff --git a/test/CodeGen/sanitize-recover.c b/test/CodeGen/sanitize-recover.c index d714d58c7f26..6358d9d04aa1 100644 --- a/test/CodeGen/sanitize-recover.c +++ b/test/CodeGen/sanitize-recover.c @@ -7,12 +7,12 @@ void test() { extern volatile unsigned x, y, z; - // RECOVER: uadd.with.overflow.i32 - // RECOVER: ubsan_handle_add_overflow( + // RECOVER: uadd.with.overflow.i32{{.*}}, !nosanitize + // RECOVER: ubsan_handle_add_overflow({{.*}}, !nosanitize // RECOVER-NOT: unreachable - // ABORT: uadd.with.overflow.i32 - // ABORT: ubsan_handle_add_overflow_abort( - // ABORT: unreachable + // ABORT: uadd.with.overflow.i32{{.*}}, !nosanitize + // ABORT: ubsan_handle_add_overflow_abort({{.*}}, !nosanitize + // ABORT: unreachable{{.*}}, !nosanitize x = y + z; } diff --git a/test/CodeGen/sparcv8-inline-asm.c b/test/CodeGen/sparcv8-inline-asm.c new file mode 100644 index 000000000000..711a2a0afbb0 --- /dev/null +++ b/test/CodeGen/sparcv8-inline-asm.c @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -triple sparc-unknown-unknown -emit-llvm %s -o - | FileCheck %s + +// CHECK: define float @fabsf(float %a) +// CHECK: %{{.*}} = call float asm sideeffect "fabss $1, $0;", "=e,f"(float %{{.*}}) #1 +float fabsf(float a) { + float res; + __asm __volatile__("fabss %1, %0;" + : /* reg out*/ "=e"(res) + : /* reg in */ "f"(a)); + return res; +} diff --git a/test/CodeGen/thinlto_backend.ll b/test/CodeGen/thinlto_backend.ll index 813bb62c1a29..86f30c0374fc 100644 --- a/test/CodeGen/thinlto_backend.ll +++ b/test/CodeGen/thinlto_backend.ll @@ -12,10 +12,10 @@ ; RUN: %clang -O2 -o %t4.o -x ir %t1.o -c -fthinlto-index=bad.thinlto.bc 2>&1 | FileCheck %s -check-prefix=CHECK-ERROR1 ; CHECK-ERROR1: Error loading index file 'bad.thinlto.bc' -; Ensure we ignore empty index file under -ignore-empty-index-file, and run -; non-ThinLTO compilation which would not import f2 +; Ensure we ignore empty index file, and run non-ThinLTO compilation which +; would not import f2 ; RUN: touch %t4.thinlto.bc -; RUN: %clang -target x86_64-unknown-linux-gnu -O2 -o %t4.o -x ir %t1.o -c -fthinlto-index=%t4.thinlto.bc -mllvm -ignore-empty-index-file +; RUN: %clang -target x86_64-unknown-linux-gnu -O2 -o %t4.o -x ir %t1.o -c -fthinlto-index=%t4.thinlto.bc ; RUN: llvm-nm %t4.o | FileCheck --check-prefix=CHECK-OBJ-IGNORE-EMPTY %s ; CHECK-OBJ-IGNORE-EMPTY: T f1 ; CHECK-OBJ-IGNORE-EMPTY: U f2 diff --git a/test/CodeGen/x86_64-mno-sse.c b/test/CodeGen/x86_64-mno-sse.c new file mode 100644 index 000000000000..43a695ae3cd3 --- /dev/null +++ b/test/CodeGen/x86_64-mno-sse.c @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -triple x86_64-linux -target-feature -sse -target-feature -sse2 -S -o /dev/null -verify %s +// REQUIRES: x86-registered-target + +double f1(void) { // expected-error {{SSE register return with SSE disabled}} + return 1.4; +} +extern double g; +void f2(void) { // expected-error {{SSE register return with SSE disabled}} + g = f1(); +} +void take_double(double); +void pass_double(void) { + // FIXME: Still asserts. + //take_double(1.5); +} diff --git a/test/CodeGen/xray-customevent.cpp b/test/CodeGen/xray-customevent.cpp new file mode 100644 index 000000000000..359d92df938a --- /dev/null +++ b/test/CodeGen/xray-customevent.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -fxray-instrument -x c++ -std=c++11 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s + +// CHECK-LABEL: @_Z16alwaysInstrumentv +[[clang::xray_always_instrument]] void alwaysInstrument() { + static constexpr char kPhase[] = "instrument"; + __xray_customevent(kPhase, 10); + // CHECK: call void @llvm.xray.customevent(i8*{{.*}}, i32 10) +} + +// CHECK-LABEL: @_Z15neverInstrumentv +[[clang::xray_never_instrument]] void neverInstrument() { + static constexpr char kPhase[] = "never"; + __xray_customevent(kPhase, 5); + // CHECK-NOT: call void @llvm.xray.customevent(i8*{{.*}}, i32 5) +} + +// CHECK-LABEL: @_Z21conditionalInstrumenti +[[clang::xray_always_instrument]] void conditionalInstrument(int v) { + static constexpr char kTrue[] = "true"; + static constexpr char kUntrue[] = "untrue"; + if (v % 2) + __xray_customevent(kTrue, 4); + else + __xray_customevent(kUntrue, 6); + + // CHECK: call void @llvm.xray.customevent(i8*{{.*}}, i32 4) + // CHECK: call void @llvm.xray.customevent(i8*{{.*}}, i32 6) +} diff --git a/test/CodeGenCXX/array-default-argument.cpp b/test/CodeGenCXX/array-default-argument.cpp new file mode 100644 index 000000000000..a07e3908392a --- /dev/null +++ b/test/CodeGenCXX/array-default-argument.cpp @@ -0,0 +1,36 @@ +// RUN: %clang_cc1 -emit-llvm -o - %s -triple %itanium_abi_triple | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -o - %s -triple %itanium_abi_triple -std=c++98 -fexceptions -fcxx-exceptions | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-EH + +struct A { + A(); + ~A(); +}; + +struct B { + B(A = A()); + ~B(); +}; + +void f(); +// CHECK-LABEL: define void @_Z1gv() +void g() { + // CHECK: br label %[[LOOP:.*]] + + // [[LOOP]]: + // CHECK: {{call|invoke}} {{.*}} @_ZN1AC1Ev([[TEMPORARY:.*]]) + // CHECK-EH: unwind label %[[PARTIAL_ARRAY_LPAD:.*]] + // CHECK: {{call|invoke}} {{.*}} @_ZN1BC1E1A({{.*}}, [[TEMPORARY]]) + // CHECK-EH: unwind label %[[A_AND_PARTIAL_ARRAY_LPAD:.*]] + // CHECK: {{call|invoke}} {{.*}} @_ZN1AD1Ev([[TEMPORARY]]) + // CHECK-EH: unwind label %[[PARTIAL_ARRAY_LPAD]] + // CHECK: getelementptr {{.*}}, i{{[0-9]*}} 1 + // CHECK: icmp eq + // CHECK: br i1 {{.*}} label %[[LOOP]] + B b[5]; + + // CHECK: {{call|invoke}} void @_Z1fv() + f(); + + // CHECK-NOT: @_ZN1AD1Ev( + // CHECK: {{call|invoke}} {{.*}} @_ZN1BD1Ev( +} diff --git a/test/CodeGenCXX/linetable-virtual-variadic.cpp b/test/CodeGenCXX/linetable-virtual-variadic.cpp index 6f966416867a..cd746cdfdfe2 100644 --- a/test/CodeGenCXX/linetable-virtual-variadic.cpp +++ b/test/CodeGenCXX/linetable-virtual-variadic.cpp @@ -12,8 +12,10 @@ void Derived::VariadicFunction(...) { } // CHECK: define void @_ZN7Derived16VariadicFunctionEz({{.*}} !dbg ![[SP:[0-9]+]] // CHECK: ret void, !dbg ![[LOC:[0-9]+]] -// CHECK-LABEL: define void @_ZT{{.+}}N7Derived16VariadicFunctionEz( -// CHECK: ret void, !dbg ![[LOC:[0-9]+]] +// CHECK: define void @_ZT{{.+}}N7Derived16VariadicFunctionEz({{.*}} !dbg ![[SP_I:[0-9]+]] +// CHECK: ret void, !dbg ![[LOC_I:[0-9]+]] // // CHECK: ![[SP]] = distinct !DISubprogram(name: "VariadicFunction" // CHECK: ![[LOC]] = !DILocation({{.*}}scope: ![[SP]]) +// CHECK: ![[SP_I]] = distinct !DISubprogram(name: "VariadicFunction" +// CHECK: ![[LOC_I]] = !DILocation({{.*}}scope: ![[SP_I]]) diff --git a/test/CodeGenCXX/vla.cpp b/test/CodeGenCXX/vla.cpp index 4e22bba7d719..957a9f9568b3 100644 --- a/test/CodeGenCXX/vla.cpp +++ b/test/CodeGenCXX/vla.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin %s -emit-llvm -o - | FileCheck %s template struct S { @@ -54,3 +54,60 @@ void test0(void *array, int n) { // CHECK-NEXT: ret void } + + +void test2(int b) { + // CHECK-LABEL: define void {{.*}}test2{{.*}}(i32 %b) + int varr[b]; + // get the address of %b by checking the first store that stores it + //CHECK: store i32 %b, i32* [[PTR_B:%.*]] + + // get the size of the VLA by getting the first load of the PTR_B + //CHECK: [[VLA_NUM_ELEMENTS_PREZEXT:%.*]] = load i32, i32* [[PTR_B]] + //CHECK-NEXT: [[VLA_NUM_ELEMENTS_PRE:%.*]] = zext i32 [[VLA_NUM_ELEMENTS_PREZEXT]] + + b = 15; + //CHECK: store i32 15, i32* [[PTR_B]] + + // Now get the sizeof, and then divide by the element size + + + //CHECK: [[VLA_SIZEOF:%.*]] = mul nuw i64 4, [[VLA_NUM_ELEMENTS_PRE]] + //CHECK-NEXT: [[VLA_NUM_ELEMENTS_POST:%.*]] = udiv i64 [[VLA_SIZEOF]], 4 + //CHECK-NEXT: [[VLA_END_PTR:%.*]] = getelementptr inbounds i32, i32* {{%.*}}, i64 [[VLA_NUM_ELEMENTS_POST]] + //CHECK-NEXT: store i32* [[VLA_END_PTR]], i32** %__end + for (int d : varr) 0; +} + +void test3(int b, int c) { + // CHECK-LABEL: define void {{.*}}test3{{.*}}(i32 %b, i32 %c) + int varr[b][c]; + // get the address of %b by checking the first store that stores it + //CHECK: store i32 %b, i32* [[PTR_B:%.*]] + //CHECK-NEXT: store i32 %c, i32* [[PTR_C:%.*]] + + // get the size of the VLA by getting the first load of the PTR_B + //CHECK: [[VLA_DIM1_PREZEXT:%.*]] = load i32, i32* [[PTR_B]] + //CHECK-NEXT: [[VLA_DIM1_PRE:%.*]] = zext i32 [[VLA_DIM1_PREZEXT]] + //CHECK: [[VLA_DIM2_PREZEXT:%.*]] = load i32, i32* [[PTR_C]] + //CHECK-NEXT: [[VLA_DIM2_PRE:%.*]] = zext i32 [[VLA_DIM2_PREZEXT]] + + b = 15; + c = 15; + //CHECK: store i32 15, i32* [[PTR_B]] + //CHECK: store i32 15, i32* [[PTR_C]] + // Now get the sizeof, and then divide by the element size + + // multiply the two dimensions, then by the element type and then divide by the sizeof dim2 + //CHECK: [[VLA_DIM1_X_DIM2:%.*]] = mul nuw i64 [[VLA_DIM1_PRE]], [[VLA_DIM2_PRE]] + //CHECK-NEXT: [[VLA_SIZEOF:%.*]] = mul nuw i64 4, [[VLA_DIM1_X_DIM2]] + //CHECK-NEXT: [[VLA_SIZEOF_DIM2:%.*]] = mul nuw i64 4, [[VLA_DIM2_PRE]] + //CHECK-NEXT: [[VLA_NUM_ELEMENTS:%.*]] = udiv i64 [[VLA_SIZEOF]], [[VLA_SIZEOF_DIM2]] + //CHECK-NEXT: [[VLA_END_INDEX:%.*]] = mul nsw i64 [[VLA_NUM_ELEMENTS]], [[VLA_DIM2_PRE]] + //CHECK-NEXT: [[VLA_END_PTR:%.*]] = getelementptr inbounds i32, i32* {{%.*}}, i64 [[VLA_END_INDEX]] + //CHECK-NEXT: store i32* [[VLA_END_PTR]], i32** %__end + + for (auto &d : varr) 0; +} + + diff --git a/test/CodeGenObjC/arc-blocks.m b/test/CodeGenObjC/arc-blocks.m index 69cd7bb297b2..b84d141037e0 100644 --- a/test/CodeGenObjC/arc-blocks.m +++ b/test/CodeGenObjC/arc-blocks.m @@ -752,6 +752,16 @@ void test19(void (^b)(void)) { // CHECK-NEXT: call void @objc_release(i8* [[X]]) // CHECK-NEXT: ret void +// CHECK-UNOPT-LABEL: define void @test20( +// CHECK-UNOPT: [[XADDR:%.*]] = alloca i8* +// CHECK-UNOPT-NEXT: [[BLOCK:%.*]] = alloca <[[BLOCKTY:.*]]> +// CHECK-UNOPT: [[CAPTUREFIELD:%.*]] = getelementptr inbounds <[[BLOCKTY]]>, <[[BLOCKTY]]>* [[BLOCK]], i32 0, i32 5 +// CHECK-UNOPT: [[BLOCKCAPTURED:%.*]] = getelementptr inbounds <[[BLOCKTY]]>, <[[BLOCKTY]]>* [[BLOCK]], i32 0, i32 5 +// CHECK-UNOPT: [[CAPTURED:%.*]] = load i8*, i8** [[XADDR]] +// CHECK-UNOPT: [[RETAINED:%.*]] = call i8* @objc_retain(i8* [[CAPTURED]]) +// CHECK-UNOPT: store i8* [[RETAINED]], i8** [[BLOCKCAPTURED]] +// CHECK-UNOPT: call void @objc_storeStrong(i8** [[CAPTUREFIELD]], i8* null) + // CHECK-LABEL: define internal void @__copy_helper_block // CHECK: [[BLOCKSOURCE:%.*]] = bitcast i8* %{{.*}} to <[[BLOCKTY]]>* // CHECK: [[CAPTUREFIELD:%.*]] = getelementptr inbounds <[[BLOCKTY]]>, <[[BLOCKTY]]>* [[BLOCKSOURCE]], i32 0, i32 5 diff --git a/test/CodeGenObjC/arc-foreach.m b/test/CodeGenObjC/arc-foreach.m index e3b3f1aa5ce4..77cb068187fa 100644 --- a/test/CodeGenObjC/arc-foreach.m +++ b/test/CodeGenObjC/arc-foreach.m @@ -68,7 +68,8 @@ void test0(NSArray *array) { // CHECK-LP64: [[D0:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 // CHECK-LP64: [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 // CHECK-LP64-NEXT: [[T1:%.*]] = load i8*, i8** [[X]] -// CHECK-LP64-NEXT: store i8* [[T1]], i8** [[T0]] +// CHECK-LP64-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]]) +// CHECK-LP64-NEXT: store i8* [[T2]], i8** [[T0]] // CHECK-LP64-NEXT: [[BLOCK1:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] // CHECK-LP64-NEXT: call void @use_block(void ()* [[BLOCK1]]) // CHECK-LP64-NEXT: call void @objc_storeStrong(i8** [[D0]], i8* null) @@ -209,7 +210,8 @@ NSArray *array4; // CHECK-LP64: [[T0:%.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, [[TY]]* }>, <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, [[TY]]* }>* [[BLOCK]], i32 0, i32 5 // CHECK-LP64: [[BC:%.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, [[TY]]* }>, <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, [[TY]]* }>* [[BLOCK]], i32 0, i32 5 // CHECK-LP64: [[T1:%.*]] = load [[TY]]*, [[TY]]** [[SELF_ADDR]] -// CHECK-LP64: store [[TY]]* [[T1]], [[TY]]** [[BC]], align 8 +// CHECK-LP64: [[T2:%.*]] = bitcast [[TY]]* [[T1]] to i8* +// CHECK-LP64: call i8* @objc_retain(i8* [[T2]]) // CHECK-LP64-OPT-LABEL: define internal void @"\01-[I1 foo2]"( // CHECK-LP64-OPT: [[TY:%.*]]* %self diff --git a/test/CodeGenOpenCL/amdgpu-debug-info-pointer-address-space.cl b/test/CodeGenOpenCL/amdgpu-debug-info-pointer-address-space.cl index c0b30095a679..7baee5eee391 100644 --- a/test/CodeGenOpenCL/amdgpu-debug-info-pointer-address-space.cl +++ b/test/CodeGenOpenCL/amdgpu-debug-info-pointer-address-space.cl @@ -58,16 +58,16 @@ kernel void kernel1( // CHECK-DAG: !DILocalVariable(name: "FuncVar4", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: ![[DWARF_ADDRESS_SPACE_NONE]]) int *FuncVar4 = Tmp1; - // CHECK-DAG: !DILocalVariable(name: "FuncVar5", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: ![[DWARF_ADDRESS_SPACE_NONE]]) - global int *constant FuncVar5 = KernelArg0; - // CHECK-DAG: !DILocalVariable(name: "FuncVar6", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: ![[DWARF_ADDRESS_SPACE_NONE]]) - constant int *constant FuncVar6 = KernelArg1; - // CHECK-DAG: !DILocalVariable(name: "FuncVar7", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: ![[DWARF_ADDRESS_SPACE_LOCAL]]) - local int *constant FuncVar7 = KernelArg2; - // CHECK-DAG: !DILocalVariable(name: "FuncVar8", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: ![[DWARF_ADDRESS_SPACE_PRIVATE]]) - private int *constant FuncVar8 = Tmp0; - // CHECK-DAG: !DILocalVariable(name: "FuncVar9", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: ![[DWARF_ADDRESS_SPACE_NONE]]) - int *constant FuncVar9 = Tmp1; + // CHECK-DAG: distinct !DIGlobalVariable(name: "FuncVar5", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: ![[DWARF_ADDRESS_SPACE_NONE]], isLocal: true, isDefinition: true) + global int *constant FuncVar5 = 0; + // CHECK-DAG: distinct !DIGlobalVariable(name: "FuncVar6", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: ![[DWARF_ADDRESS_SPACE_NONE]], isLocal: true, isDefinition: true) + constant int *constant FuncVar6 = 0; + // CHECK-DAG: distinct !DIGlobalVariable(name: "FuncVar7", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: ![[DWARF_ADDRESS_SPACE_LOCAL]], isLocal: true, isDefinition: true) + local int *constant FuncVar7 = 0; + // CHECK-DAG: distinct !DIGlobalVariable(name: "FuncVar8", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: ![[DWARF_ADDRESS_SPACE_PRIVATE]], isLocal: true, isDefinition: true) + private int *constant FuncVar8 = 0; + // CHECK-DAG: distinct !DIGlobalVariable(name: "FuncVar9", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: ![[DWARF_ADDRESS_SPACE_NONE]], isLocal: true, isDefinition: true) + int *constant FuncVar9 = 0; // CHECK-DAG: distinct !DIGlobalVariable(name: "FuncVar10", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: ![[DWARF_ADDRESS_SPACE_NONE]], isLocal: true, isDefinition: true) global int *local FuncVar10; FuncVar10 = KernelArg0; diff --git a/test/CodeGenOpenCL/amdgpu-debug-info-variable-expression.cl b/test/CodeGenOpenCL/amdgpu-debug-info-variable-expression.cl index a962d3c75aaf..c0a4c21ce760 100644 --- a/test/CodeGenOpenCL/amdgpu-debug-info-variable-expression.cl +++ b/test/CodeGenOpenCL/amdgpu-debug-info-variable-expression.cl @@ -80,21 +80,21 @@ kernel void kernel1( // CHECK-DAG: call void @llvm.dbg.declare(metadata i32 addrspace(4)** {{.*}}, metadata ![[FUNCVAR4]], metadata ![[PRIVATE]]), !dbg !{{[0-9]+}} int *FuncVar4 = Tmp1; - // CHECK-DAG: ![[FUNCVAR5:[0-9]+]] = !DILocalVariable(name: "FuncVar5", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: !{{[0-9]+}}) - // CHECK-DAG: call void @llvm.dbg.declare(metadata i32 addrspace(1)** {{.*}}, metadata ![[FUNCVAR5]], metadata ![[NONE:[0-9]+]]), !dbg !{{[0-9]+}} - global int *constant FuncVar5 = KernelArg0; - // CHECK-DAG: ![[FUNCVAR6:[0-9]+]] = !DILocalVariable(name: "FuncVar6", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: !{{[0-9]+}}) - // CHECK-DAG: call void @llvm.dbg.declare(metadata i32 addrspace(2)** {{.*}}, metadata ![[FUNCVAR6]], metadata ![[NONE]]), !dbg !{{[0-9]+}} - constant int *constant FuncVar6 = KernelArg1; - // CHECK-DAG: ![[FUNCVAR7:[0-9]+]] = !DILocalVariable(name: "FuncVar7", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: !{{[0-9]+}}) - // CHECK-DAG: call void @llvm.dbg.declare(metadata i32 addrspace(3)** {{.*}}, metadata ![[FUNCVAR7]], metadata ![[NONE]]), !dbg !{{[0-9]+}} - local int *constant FuncVar7 = KernelArg2; - // CHECK-DAG: ![[FUNCVAR8:[0-9]+]] = !DILocalVariable(name: "FuncVar8", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: !{{[0-9]+}}) - // CHECK-DAG: call void @llvm.dbg.declare(metadata i32** {{.*}}, metadata ![[FUNCVAR8]], metadata ![[NONE]]), !dbg !{{[0-9]+}} - private int *constant FuncVar8 = Tmp0; - // CHECK-DAG: ![[FUNCVAR9:[0-9]+]] = !DILocalVariable(name: "FuncVar9", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: !{{[0-9]+}}) - // CHECK-DAG: call void @llvm.dbg.declare(metadata i32 addrspace(4)** {{.*}}, metadata ![[FUNCVAR9]], metadata ![[NONE]]), !dbg !{{[0-9]+}} - int *constant FuncVar9 = Tmp1; + // CHECK-DAG: ![[FUNCVAR5:[0-9]+]] = distinct !DIGlobalVariable(name: "FuncVar5", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: !{{[0-9]+}}, isLocal: true, isDefinition: true) + // CHECK-DAG: !DIGlobalVariableExpression(var: ![[FUNCVAR5]]) + global int *constant FuncVar5 = 0; + // CHECK-DAG: ![[FUNCVAR6:[0-9]+]] = distinct !DIGlobalVariable(name: "FuncVar6", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: !{{[0-9]+}}, isLocal: true, isDefinition: true) + // CHECK-DAG: !DIGlobalVariableExpression(var: ![[FUNCVAR6]]) + constant int *constant FuncVar6 = 0; + // CHECK-DAG: ![[FUNCVAR7:[0-9]+]] = distinct !DIGlobalVariable(name: "FuncVar7", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: !{{[0-9]+}}, isLocal: true, isDefinition: true) + // CHECK-DAG: !DIGlobalVariableExpression(var: ![[FUNCVAR7]]) + local int *constant FuncVar7 = 0; + // CHECK-DAG: ![[FUNCVAR8:[0-9]+]] = distinct !DIGlobalVariable(name: "FuncVar8", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: !{{[0-9]+}}, isLocal: true, isDefinition: true) + // CHECK-DAG: !DIGlobalVariableExpression(var: ![[FUNCVAR8]]) + private int *constant FuncVar8 = 0; + // CHECK-DAG: ![[FUNCVAR9:[0-9]+]] = distinct !DIGlobalVariable(name: "FuncVar9", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: !{{[0-9]+}}, isLocal: true, isDefinition: true) + // CHECK-DAG: !DIGlobalVariableExpression(var: ![[FUNCVAR9]]) + int *constant FuncVar9 = 0; // CHECK-DAG: ![[FUNCVAR10:[0-9]+]] = distinct !DIGlobalVariable(name: "FuncVar10", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: !{{[0-9]+}}, isLocal: true, isDefinition: true) // CHECK-DAG: !DIGlobalVariableExpression(var: ![[FUNCVAR10]], expr: ![[LOCAL]]) diff --git a/test/CodeGenOpenCL/constant-addr-space-globals.cl b/test/CodeGenOpenCL/constant-addr-space-globals.cl index 4f0d1ea23e56..7bb970527c26 100644 --- a/test/CodeGenOpenCL/constant-addr-space-globals.cl +++ b/test/CodeGenOpenCL/constant-addr-space-globals.cl @@ -11,10 +11,11 @@ kernel void test(global float *out) { // but create a copy in the original address space (unless a variable itself is // in the constant address space). -void foo(constant const int *p1, const int *p2, const int *p3); +void foo(constant int* p, constant const int *p1, const int *p2, const int *p3); // CHECK: @k.arr1 = internal addrspace(2) constant [3 x i32] [i32 1, i32 2, i32 3] // CHECK: @k.arr2 = private unnamed_addr addrspace(2) constant [3 x i32] [i32 4, i32 5, i32 6] // CHECK: @k.arr3 = private unnamed_addr addrspace(2) constant [3 x i32] [i32 7, i32 8, i32 9] +// CHECK: @k.var1 = internal addrspace(2) constant i32 1 kernel void k(void) { // CHECK-NOT: %arr1 = alloca [3 x i32] constant const int arr1[] = {1, 2, 3}; @@ -23,5 +24,8 @@ kernel void k(void) { // CHECK: %arr3 = alloca [3 x i32] int arr3[] = {7, 8, 9}; - foo(arr1, arr2, arr3); + constant int var1 = 1; + + // CHECK: call spir_func void @foo(i32 addrspace(2)* @k.var1, i32 addrspace(2)* getelementptr inbounds ([3 x i32], [3 x i32] addrspace(2)* @k.arr1, i32 0, i32 0) + foo(&var1, arr1, arr2, arr3); } diff --git a/test/Driver/fsanitize.c b/test/Driver/fsanitize.c index 05e239c74243..41f573aa7316 100644 --- a/test/Driver/fsanitize.c +++ b/test/Driver/fsanitize.c @@ -30,7 +30,7 @@ // RUN: %clang -target x86_64-pc-win32 -fsanitize-coverage=bb %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-COVERAGE-WIN64 // CHECK-COVERAGE-WIN64: "--dependent-lib={{[^"]*}}ubsan_standalone-x86_64.lib" -// RUN: %clang -target x86_64-linux-gnu -fsanitize=integer %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-INTEGER +// RUN: %clang -target x86_64-linux-gnu -fsanitize=integer %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-INTEGER -implicit-check-not="-fsanitize-address-use-after-scope" // CHECK-INTEGER: "-fsanitize={{((signed-integer-overflow|unsigned-integer-overflow|integer-divide-by-zero|shift-base|shift-exponent),?){5}"}} // RUN: %clang -fsanitize=bounds -### -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix=CHECK-BOUNDS @@ -126,6 +126,13 @@ // RUN: %clang -target x86_64-linux-gnu -fsanitize=address %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-WITHOUT-USE-AFTER-SCOPE // CHECK-ASAN-WITHOUT-USE-AFTER-SCOPE: -cc1{{.*}}address-use-after-scope +// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-address-globals-dead-stripping %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-GLOBALS +// RUN: %clang -target x86_64-linux-gnu -fsanitize=address %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-ASAN-GLOBALS +// RUN: %clang_cl --target=x86_64-windows-msvc -fsanitize=address -fsanitize-address-globals-dead-stripping -### -- %s 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-GLOBALS +// RUN: %clang_cl --target=x86_64-windows-msvc -fsanitize=address -### -- %s 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-GLOBALS +// CHECK-ASAN-GLOBALS: -cc1{{.*}}-fsanitize-address-globals-dead-stripping +// CHECK-NO-ASAN-GLOBALS-NOT: -cc1{{.*}}-fsanitize-address-globals-dead-stripping + // RUN: %clang -target x86_64-linux-gnu -fsanitize-memory-track-origins -pie %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ONLY-TRACK-ORIGINS // CHECK-ONLY-TRACK-ORIGINS: warning: argument unused during compilation: '-fsanitize-memory-track-origins' diff --git a/test/Driver/myriad-toolchain.c b/test/Driver/myriad-toolchain.c index 971e5d3e6961..7bd215bf1a48 100644 --- a/test/Driver/myriad-toolchain.c +++ b/test/Driver/myriad-toolchain.c @@ -54,9 +54,11 @@ // -fno-split-dwarf-inlining is consumed but not passed to moviCompile. // RUN: %clang -target shave-myriad -c -### %s -g -fno-inline-functions \ // RUN: -fno-inline-functions-called-once -Os -Wall -MF dep.d -fno-split-dwarf-inlining \ -// RUN: -ffunction-sections 2>&1 | FileCheck %s -check-prefix=PASSTHRU_OPTIONS +// RUN: -ffunction-sections -Xclang -xclangflag -mllvm -llvm-flag 2>&1 \ +// RUN: | FileCheck %s -check-prefix=PASSTHRU_OPTIONS // PASSTHRU_OPTIONS: "-g" "-fno-inline-functions" "-fno-inline-functions-called-once" // PASSTHRU_OPTIONS: "-Os" "-Wall" "-MF" "dep.d" "-ffunction-sections" +// PASSTHRU_OPTIONS: "-Xclang" "-xclangflag" "-mllvm" "-llvm-flag" // RUN: %clang -target shave-myriad -c %s -o foo.o -### -MD -MF dep.d 2>&1 \ // RUN: | FileCheck %s -check-prefix=MDMF diff --git a/test/Driver/wasm-toolchain.c b/test/Driver/wasm-toolchain.c index d0b029303891..3be60df92672 100644 --- a/test/Driver/wasm-toolchain.c +++ b/test/Driver/wasm-toolchain.c @@ -27,18 +27,18 @@ // RUN: %clang -### -no-canonical-prefixes -target wasm32-unknown-unknown --sysroot=/foo %s 2>&1 | FileCheck -check-prefix=LINK %s // LINK: clang{{.*}}" "-cc1" {{.*}} "-o" "[[temp:[^"]*]]" -// LINK: lld{{.*}}" "-flavor" "ld" "-L/foo/lib32" "crt1.o" "crti.o" "[[temp]]" "-lc" "-lcompiler_rt" "crtn.o" "-o" "a.out" +// LINK: lld{{.*}}" "-flavor" "wasm" "-L/foo/lib32" "crt1.o" "crti.o" "[[temp]]" "-lc" "-lcompiler_rt" "crtn.o" "-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 --sysroot=/foo %s 2>&1 | FileCheck -check-prefix=LINK_OPT %s // LINK_OPT: clang{{.*}}" "-cc1" {{.*}} "-o" "[[temp:[^"]*]]" -// LINK_OPT: lld{{.*}}" "-flavor" "ld" "--gc-sections" "-L/foo/lib32" "crt1.o" "crti.o" "[[temp]]" "-lc" "-lcompiler_rt" "crtn.o" "-o" "a.out" +// LINK_OPT: lld{{.*}}" "-flavor" "wasm" "--gc-sections" "-L/foo/lib32" "crt1.o" "crti.o" "[[temp]]" "-lc" "-lcompiler_rt" "crtn.o" "-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 --sysroot=/foo -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" "-L/foo/lib32" "crt1.o" "crti.o" "--no-gc-sections" "[[temp]]" "-lc" "-lcompiler_rt" "crtn.o" "-o" "a.out" +// NO_GC_SECTIONS: lld{{.*}}" "-flavor" "wasm" "--gc-sections" "-L/foo/lib32" "crt1.o" "crti.o" "--no-gc-sections" "[[temp]]" "-lc" "-lcompiler_rt" "crtn.o" "-o" "a.out" diff --git a/test/FixIt/fixit-availability.c b/test/FixIt/fixit-availability.c index fa641b4b98c6..038dee08b13c 100644 --- a/test/FixIt/fixit-availability.c +++ b/test/FixIt/fixit-availability.c @@ -5,6 +5,6 @@ int function(void); void use() { function(); -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:3}:"if (__builtin_available(macos 10.12, *)) {\n " +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:3}:"if (__builtin_available(macOS 10.12, *)) {\n " // CHECK-NEXT: fix-it:{{.*}}:{[[@LINE-2]]:14-[[@LINE-2]]:14}:"\n } else {\n // Fallback on earlier versions\n }" } diff --git a/test/FixIt/fixit-availability.mm b/test/FixIt/fixit-availability.mm index 6bf8f49ddc0d..d044a73efdb9 100644 --- a/test/FixIt/fixit-availability.mm +++ b/test/FixIt/fixit-availability.mm @@ -7,58 +7,58 @@ void anotherFunction(int function); int use() { function(); -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:3}:"if (@available(macos 10.12, *)) {\n " +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:3}:"if (@available(macOS 10.12, *)) {\n " // CHECK-NEXT: fix-it:{{.*}}:{[[@LINE-2]]:14-[[@LINE-2]]:14}:"\n } else {\n // Fallback on earlier versions\n }" int y = function(), x = 0; -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:3}:"if (@available(macos 10.12, *)) {\n " +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:3}:"if (@available(macOS 10.12, *)) {\n " // CHECK-NEXT: fix-it:{{.*}}:{[[@LINE-2]]:29-[[@LINE-2]]:29}:"\n } else {\n // Fallback on earlier versions\n }" x += function(); -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:3}:"if (@available(macos 10.12, *)) {\n " +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:3}:"if (@available(macOS 10.12, *)) {\n " // CHECK-NEXT: fix-it:{{.*}}:{[[@LINE-2]]:19-[[@LINE-2]]:19}:"\n } else {\n // Fallback on earlier versions\n }" if (1) { x = function(); -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:5-[[@LINE-1]]:5}:"if (@available(macos 10.12, *)) {\n " +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:5-[[@LINE-1]]:5}:"if (@available(macOS 10.12, *)) {\n " // CHECK-NEXT: fix-it:{{.*}}:{[[@LINE-2]]:20-[[@LINE-2]]:20}:"\n } else {\n // Fallback on earlier versions\n }" } anotherFunction(function()); -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:3}:"if (@available(macos 10.12, *)) {\n " +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:3}:"if (@available(macOS 10.12, *)) {\n " // CHECK-NEXT: fix-it:{{.*}}:{[[@LINE-2]]:31-[[@LINE-2]]:31}:"\n } else {\n // Fallback on earlier versions\n }" if (function()) { -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:3}:"if (@available(macos 10.12, *)) {\n " +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:3}:"if (@available(macOS 10.12, *)) {\n " // CHECK-NEXT: fix-it:{{.*}}:{[[@LINE+1]]:4-[[@LINE+1]]:4}:"\n } else {\n // Fallback on earlier versions\n }" } while (function()) - // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:3}:"if (@available(macos 10.12, *)) {\n " + // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:3}:"if (@available(macOS 10.12, *)) {\n " // CHECK-NEXT: fix-it:{{.*}}:{[[@LINE+1]]:6-[[@LINE+1]]:6}:"\n } else {\n // Fallback on earlier versions\n }" ; do function(); -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:5-[[@LINE-1]]:5}:"if (@available(macos 10.12, *)) {\n " +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:5-[[@LINE-1]]:5}:"if (@available(macOS 10.12, *)) {\n " // CHECK-NEXT: fix-it:{{.*}}:{[[@LINE-2]]:16-[[@LINE-2]]:16}:"\n } else {\n // Fallback on earlier versions\n }" while (1); for (int i = 0; i < 10; ++i) function(); -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:5-[[@LINE-1]]:5}:"if (@available(macos 10.12, *)) {\n " +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:5-[[@LINE-1]]:5}:"if (@available(macOS 10.12, *)) {\n " // CHECK-NEXT: fix-it:{{.*}}:{[[@LINE-2]]:16-[[@LINE-2]]:16}:"\n } else {\n // Fallback on earlier versions\n }" switch (x) { case 0: function(); -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:5-[[@LINE-1]]:5}:"if (@available(macos 10.12, *)) {\n " +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:5-[[@LINE-1]]:5}:"if (@available(macOS 10.12, *)) {\n " // CHECK-NEXT: fix-it:{{.*}}:{[[@LINE-2]]:16-[[@LINE-2]]:16}:"\n } else {\n // Fallback on earlier versions\n }" case 2: anotherFunction(1); function(); -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:5-[[@LINE-1]]:5}:"if (@available(macos 10.12, *)) {\n " +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:5-[[@LINE-1]]:5}:"if (@available(macOS 10.12, *)) {\n " // CHECK-NEXT: fix-it:{{.*}}:{[[@LINE-2]]:16-[[@LINE-2]]:16}:"\n } else {\n // Fallback on earlier versions\n }" break; default: function(); -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:5-[[@LINE-1]]:5}:"if (@available(macos 10.12, *)) {\n " +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:5-[[@LINE-1]]:5}:"if (@available(macOS 10.12, *)) {\n " // CHECK-NEXT: fix-it:{{.*}}:{[[@LINE-2]]:16-[[@LINE-2]]:16}:"\n } else {\n // Fallback on earlier versions\n }" break; } return function(); -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:3}:"if (@available(macos 10.12, *)) {\n " +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:3}:"if (@available(macOS 10.12, *)) {\n " // CHECK-NEXT: fix-it:{{.*}}:{[[@LINE-2]]:21-[[@LINE-2]]:21}:"\n } else {\n // Fallback on earlier versions\n }" } @@ -72,39 +72,39 @@ int use() { void useInMacros() { MYFUNCTION(); -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:3}:"if (@available(macos 10.12, *)) {\n " +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:3}:"if (@available(macOS 10.12, *)) {\n " // CHECK-NEXT: fix-it:{{.*}}:{[[@LINE-2]]:16-[[@LINE-2]]:16}:"\n } else {\n // Fallback on earlier versions\n }" MACRO_ARGUMENT_SEMI(function()) -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:3}:"if (@available(macos 10.12, *)) {\n " +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:3}:"if (@available(macOS 10.12, *)) {\n " // CHECK-NEXT: fix-it:{{.*}}:{[[@LINE-2]]:34-[[@LINE-2]]:34}:"\n } else {\n // Fallback on earlier versions\n }" MACRO_ARGUMENT(function()); -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:3}:"if (@available(macos 10.12, *)) {\n " +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:3}:"if (@available(macOS 10.12, *)) {\n " // CHECK-NEXT: fix-it:{{.*}}:{[[@LINE-2]]:30-[[@LINE-2]]:30}:"\n } else {\n // Fallback on earlier versions\n }" MACRO_ARGUMENT_2(function()); -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:3}:"if (@available(macos 10.12, *)) {\n " +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:3}:"if (@available(macOS 10.12, *)) {\n " // CHECK-NEXT: fix-it:{{.*}}:{[[@LINE-2]]:32-[[@LINE-2]]:32}:"\n } else {\n // Fallback on earlier versions\n }" INNER_MACRO -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:3}:"if (@available(macos 10.12, *)) {\n " +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:3}:"if (@available(macOS 10.12, *)) {\n " // CHECK-NEXT: fix-it:{{.*}}:{[[@LINE-2]]:14-[[@LINE-2]]:14}:"\n } else {\n // Fallback on earlier versions\n }" } void wrapDeclStmtUses() { int x = 0, y = function(); -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:3}:"if (@available(macos 10.12, *)) {\n " +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:3}:"if (@available(macOS 10.12, *)) {\n " // CHECK-NEXT: fix-it:{{.*}}:{[[@LINE+13]]:22-[[@LINE+13]]:22}:"\n } else {\n // Fallback on earlier versions\n }" { int z = function(); if (z) { } -// CHECK: fix-it:{{.*}}:{[[@LINE-4]]:5-[[@LINE-4]]:5}:"if (@available(macos 10.12, *)) {\n " +// CHECK: fix-it:{{.*}}:{[[@LINE-4]]:5-[[@LINE-4]]:5}:"if (@available(macOS 10.12, *)) {\n " // CHECK-NEXT: fix-it:{{.*}}:{[[@LINE-2]]:6-[[@LINE-2]]:6}:"\n } else {\n // Fallback on earlier versions\n }" } if (y) int z = function(); -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:5-[[@LINE-1]]:5}:"if (@available(macos 10.12, *)) {\n " +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:5-[[@LINE-1]]:5}:"if (@available(macOS 10.12, *)) {\n " // CHECK-NEXT: fix-it:{{.*}}:{[[@LINE-2]]:24-[[@LINE-2]]:24}:"\n } else {\n // Fallback on earlier versions\n }" anotherFunction(y); anotherFunction(x); diff --git a/test/Import/conflicting-struct/Inputs/S1.cpp b/test/Import/conflicting-struct/Inputs/S1.cpp new file mode 100644 index 000000000000..a99dba8c7821 --- /dev/null +++ b/test/Import/conflicting-struct/Inputs/S1.cpp @@ -0,0 +1,6 @@ +class T; + +class S { + T *t; + int a; +}; diff --git a/test/Import/conflicting-struct/Inputs/S2.cpp b/test/Import/conflicting-struct/Inputs/S2.cpp new file mode 100644 index 000000000000..de2cb6cd03c7 --- /dev/null +++ b/test/Import/conflicting-struct/Inputs/S2.cpp @@ -0,0 +1,7 @@ +class U { + int b; +}; + +class T { + U u; +}; diff --git a/test/Import/conflicting-struct/test.cpp b/test/Import/conflicting-struct/test.cpp new file mode 100644 index 000000000000..5aad567cd794 --- /dev/null +++ b/test/Import/conflicting-struct/test.cpp @@ -0,0 +1,7 @@ +// RUN: clang-import-test --import %S/Inputs/S1.cpp --import %S/Inputs/S2.cpp -expression %s +void expr() { + S MyS; + T MyT; + MyS.a = 3; + MyT.u.b = 2; +} diff --git a/test/Index/Core/index-dependent-source.cpp b/test/Index/Core/index-dependent-source.cpp new file mode 100644 index 000000000000..8c097b935a37 --- /dev/null +++ b/test/Index/Core/index-dependent-source.cpp @@ -0,0 +1,143 @@ +// RUN: c-index-test core -print-source-symbols -- %s -std=c++14 -target x86_64-apple-macosx10.7 | FileCheck %s + +int invalid; + +class Base { + void baseFunction(); + + int baseField; + + static void staticBaseFunction(); +}; + +template +class BaseTemplate { +public: + T baseTemplateFunction(); + + T baseTemplateField; + + static T baseTemplateVariable; +}; + +template +class TemplateClass: public Base , public BaseTemplate { +public: + ~TemplateClass(); + + T function() { } + + static void staticFunction() { } + + T field; + + static T variable; + + struct Struct { }; + + enum Enum { EnumValue }; + + using TypeAlias = S; + typedef T Typedef; + + void overload1(const T &); + void overload1(const S &); +}; + +template +void indexSimpleDependentDeclarations(const TemplateClass &object) { + // Valid instance members: + object.function(); +// CHECK: [[@LINE-1]]:10 | instance-method/C++ | function | c:@ST>2#T#T@TemplateClass@F@function# | | Ref,Call,RelCall,RelCont | rel: 1 + object.field; +// CHECK: [[@LINE-1]]:10 | field/C++ | field | c:@ST>2#T#T@TemplateClass@FI@field | | Ref,RelCont | rel: 1 + object.baseFunction(); +// CHECK: [[@LINE-1]]:10 | instance-method/C++ | baseFunction | c:@S@Base@F@baseFunction# | __ZN4Base12baseFunctionEv | Ref,Call,RelCall,RelCont | rel: 1 + object.baseField; +// CHECK: [[@LINE-1]]:10 | field/C++ | baseField | c:@S@Base@FI@baseField | | Ref,RelCont | rel: 1 + object.baseTemplateFunction(); +// CHECK: [[@LINE-1]]:10 | instance-method/C++ | baseTemplateFunction | c:@ST>1#T@BaseTemplate@F@baseTemplateFunction# | | Ref,Call,RelCall,RelCont | rel: 1 + object.baseTemplateField; +// CHECK: [[@LINE-1]]:10 | field/C++ | baseTemplateField | c:@ST>1#T@BaseTemplate@FI@baseTemplateField | | Ref,RelCont | rel: 1 + + // Invalid instance members: + object.variable; +// CHECK-NOT: [[@LINE-1]]:10 + object.staticFunction(); +// CHECK-NOT: [[@LINE-1]]:10 + object.Struct; +// CHECK-NOT: [[@LINE-1]]:10 + object.EnumValue; +// CHECK-NOT: [[@LINE-1]]:10 + + // Valid static members: + TemplateClass::staticFunction(); +// CHECK: [[@LINE-1]]:24 | static-method/C++ | staticFunction | c:@ST>2#T#T@TemplateClass@F@staticFunction#S | | Ref,Call,RelCall,RelCont | rel: 1 + TemplateClass::variable; +// CHECK: [[@LINE-1]]:24 | static-property/C++ | variable | c:@ST>2#T#T@TemplateClass@variable | __ZN13TemplateClass8variableE | Ref,RelCont | rel: 1 + TemplateClass::staticBaseFunction(); +// CHECK: [[@LINE-1]]:24 | static-method/C++ | staticBaseFunction | c:@S@Base@F@staticBaseFunction#S | __ZN4Base18staticBaseFunctionEv | Ref,Call,RelCall,RelCont | rel: 1 + TemplateClass::baseTemplateVariable; +// CHECK: [[@LINE-1]]:24 | static-property/C++ | baseTemplateVariable | c:@ST>1#T@BaseTemplate@baseTemplateVariable | __ZN12BaseTemplate20baseTemplateVariableE | Ref,RelCont | rel: 1 + TemplateClass::EnumValue; +// CHECK: [[@LINE-1]]:24 | enumerator/C | EnumValue | c:@ST>2#T#T@TemplateClass@E@Enum@EnumValue | | Ref,RelCont | rel: 1 + TemplateClass::Struct(); +// CHECK: [[@LINE-1]]:24 | struct/C | Struct | c:@ST>2#T#T@TemplateClass@S@Struct | | Ref,Call,RelCall,RelCont | rel: 1 + + // Invalid static members: + TemplateClass::field; +// CHECK-NOT: [[@LINE-1]]:24 + TemplateClass::function(); +// CHECK-NOT: [[@LINE-1]]:24 + + // Valid type names: + typename TemplateClass::Struct Val; +// CHECK: [[@LINE-1]]:33 | struct/C | Struct | c:@ST>2#T#T@TemplateClass@S@Struct | | Ref,RelCont | rel: 1 + typename TemplateClass::Enum EnumVal; +// CHECK: [[@LINE-1]]:33 | enum/C | Enum | c:@ST>2#T#T@TemplateClass@E@Enum | | Ref,RelCont | rel: 1 + typename TemplateClass::TypeAlias Val2; +// CHECK: [[@LINE-1]]:33 | type-alias/C++ | TypeAlias | c:@ST>2#T#T@TemplateClass@TypeAlias | | Ref,RelCont | rel: 1 + typename TemplateClass::Typedef Val3; +// CHECK: [[@LINE-1]]:33 | type-alias/C | Typedef | c:{{.*}}index-dependent-source.cpp@ST>2#T#T@TemplateClass@T@Typedef | | Ref,RelCont | rel: 1 + + // Invalid type names: + typename TemplateClass::field Val4; +// CHECK-NOT: [[@LINE-1]]:33 + typename TemplateClass::staticFunction Val5; +// CHECK-NOT: [[@LINE-1]]:33 + + + object.invalid; +// CHECK-NOT: [[@LINE-1]]:10 + TemplateClass::invalid; +// CHECK-NOT: [[@LINE-1]]:24 +} + +template +void indexDependentOverloads(const TemplateClass &object) { + object.overload1(T()); +// CHECK-NOT: [[@LINE-1]] + object.overload1(S()); +// CHECK-NOT: [[@LINE-1]] + object.overload1(Y()); +// CHECK-NOT: [[@LINE-1]] +} + +template struct UndefinedTemplateClass; + +template +void undefinedTemplateLookup(UndefinedTemplateClass &x) { +// Shouldn't crash! + x.lookup; + typename UndefinedTemplateClass::Type y; +} + +template +struct UserOfUndefinedTemplateClass: UndefinedTemplateClass { }; + +template +void undefinedTemplateLookup2(UserOfUndefinedTemplateClass &x) { +// Shouldn't crash! + x.lookup; + typename UserOfUndefinedTemplateClass::Type y; +} diff --git a/test/Index/Core/index-instantiated-source.cpp b/test/Index/Core/index-instantiated-source.cpp new file mode 100644 index 000000000000..f61795da540c --- /dev/null +++ b/test/Index/Core/index-instantiated-source.cpp @@ -0,0 +1,39 @@ +// RUN: c-index-test core -print-source-symbols -- %s -std=c++14 -target x86_64-apple-macosx10.7 | FileCheck %s +// References to declarations in instantiations should be canonicalized: + +template +class BaseTemplate { +public: + T baseTemplateFunction(); +// CHECK: [[@LINE-1]]:5 | instance-method/C++ | baseTemplateFunction | c:@ST>1#T@BaseTemplate@F@baseTemplateFunction# + + T baseTemplateField; +// CHECK: [[@LINE-1]]:5 | field/C++ | baseTemplateField | c:@ST>1#T@BaseTemplate@FI@baseTemplateField +}; + +template +class TemplateClass: public BaseTemplate { +public: + T function() { return T(); } +// CHECK: [[@LINE-1]]:5 | instance-method/C++ | function | c:@ST>2#T#T@TemplateClass@F@function# + + static void staticFunction() { } +// CHECK: [[@LINE-1]]:15 | static-method/C++ | staticFunction | c:@ST>2#T#T@TemplateClass@F@staticFunction#S + + T field; +// CHECK: [[@LINE-1]]:5 | field/C++ | field | c:@ST>2#T#T@TemplateClass@FI@field +}; + +void canonicalizeInstaniationReferences(TemplateClass &object) { + (void)object.function(); +// CHECK: [[@LINE-1]]:16 | instance-method/C++ | function | c:@ST>2#T#T@TemplateClass@F@function# | + (void)object.field; +// CHECK: [[@LINE-1]]:16 | field/C++ | field | c:@ST>2#T#T@TemplateClass@FI@field | | Ref,RelCont | rel: 1 + (void)object.baseTemplateFunction(); +// CHECK: [[@LINE-1]]:16 | instance-method/C++ | baseTemplateFunction | c:@ST>1#T@BaseTemplate@F@baseTemplateFunction# | + (void)object.baseTemplateField; +// CHECK: [[@LINE-1]]:16 | field/C++ | baseTemplateField | c:@ST>1#T@BaseTemplate@FI@baseTemplateField | | Ref,RelCont | rel: 1 + + TemplateClass::staticFunction(); +// CHECK: [[@LINE-1]]:30 | static-method/C++ | staticFunction | c:@ST>2#T#T@TemplateClass@F@staticFunction#S | : Cls { }; // CHECK-NEXT: [[@LINE-5]]:7 | class(Gen)/C++ | PartialSpecilizationClass | c:@ST>2#T#T@PartialSpecilizationClass | | Ref | rel: 0 // CHECK-NEXT: [[@LINE-6]]:33 | class/C++ | Cls | c:@S@Cls | | Ref | rel: 0 // CHECK-NEXT: [[@LINE-7]]:38 | class/C++ | Cls | c:@S@Cls | | Ref | rel: 0 + +template +void functionSp() { } + +struct Record { + constexpr static int C = 2; +}; + +template<> +void functionSp, Record::C>() { +// CHECK: [[@LINE-1]]:6 | function(Gen,TS)/C++ | functionSp | c:@F@functionSp<#$@S@SpecializationDecl>#$@S@Cls#VI2># | __Z10functionSpI18SpecializationDeclI3ClsELi2EEvv | Def,RelSpecialization | rel: 1 +// CHECK: RelSpecialization | functionSp | c:@FT@>2#T#NIfunctionSp#v# +// CHECK: [[@LINE-3]]:17 | class(Gen)/C++ | SpecializationDecl | c:@ST>1#T@SpecializationDecl | | Ref,RelCont | rel: 1 +// CHECK: [[@LINE-4]]:36 | class/C++ | Cls | c:@S@Cls | | Ref,RelCont | rel: 1 +// CHECK: [[@LINE-5]]:50 | static-property/C++ | C | c:@S@Record@C | __ZN6Record1CE | Ref,RelCont | rel: 1 +// CHECK: [[@LINE-6]]:42 | struct/C++ | Record | c:@S@Record | | Ref,RelCont | rel: 1 +} + +template +class ClassWithCorrectSpecialization { }; + +template<> +class ClassWithCorrectSpecialization, Record::C> { }; +// CHECK: [[@LINE-1]]:38 | class(Gen)/C++ | SpecializationDecl | c:@ST>1#T@SpecializationDecl | | Ref | rel: 0 +// CHECK: [[@LINE-2]]:57 | class/C++ | Cls | c:@S@Cls | | Ref | rel: 0 +// CHECK: [[@LINE-3]]:71 | static-property/C++ | C | c:@S@Record@C | __ZN6Record1CE | Ref,Read | rel: 0 +// CHECK: [[@LINE-4]]:63 | struct/C++ | Record | c:@S@Record | | Ref | rel: 0 + +namespace ns { +// CHECK: [[@LINE-1]]:11 | namespace/C++ | ns | c:@N@ns | | Decl | rel: 0 +namespace inner { +// CHECK: [[@LINE-1]]:11 | namespace/C++ | inner | c:@N@ns@N@inner | | Decl,RelChild | rel: 1 +void func(); + +} +namespace innerAlias = inner; +// CHECK: [[@LINE-1]]:11 | namespace-alias/C++ | innerAlias | c:@N@ns@NA@innerAlias | | Decl,RelChild | rel: 1 +// CHECK: [[@LINE-2]]:24 | namespace/C++ | inner | c:@N@ns@N@inner | | Ref,RelCont | rel: 1 +} + +namespace namespaceAlias = ::ns::innerAlias; +// CHECK: [[@LINE-1]]:11 | namespace-alias/C++ | namespaceAlias | c:@NA@namespaceAlias | | Decl | rel: 0 +// CHECK: [[@LINE-2]]:30 | namespace/C++ | ns | c:@N@ns | | Ref,RelCont | rel: 1 +// CHECK: [[@LINE-3]]:34 | namespace-alias/C++ | innerAlias | c:@N@ns@NA@innerAlias | | Ref,RelCont | rel: 1 + +void ::ns::inner::func() { +// CHECK: [[@LINE-1]]:8 | namespace/C++ | ns | c:@N@ns | | Ref,RelCont | rel: 1 +// CHECK: [[@LINE-2]]:12 | namespace/C++ | inner | c:@N@ns@N@inner | | Ref,RelCont | rel: 1 + ns::innerAlias::func(); +// CHECK: [[@LINE-1]]:3 | namespace/C++ | ns | c:@N@ns | | Ref,RelCont | rel: 1 +// CHECK: [[@LINE-2]]:7 | namespace-alias/C++ | innerAlias | c:@N@ns@NA@innerAlias | | Ref,RelCont | rel: 1 +} diff --git a/test/Index/complete-available.m b/test/Index/complete-available.m new file mode 100644 index 000000000000..8267dbdddc5c --- /dev/null +++ b/test/Index/complete-available.m @@ -0,0 +1,20 @@ +/* The run lines are below, because this test is line- and + column-number sensitive. */ +void atAvailable() { + if (@available(macOS 10.10, *)) { + + } + if (__builtin_available(iOS 8, *)) { + } +} + +// RUN: c-index-test -code-completion-at=%s:4:18 %s | FileCheck -check-prefix=CHECK %s +// RUN: c-index-test -code-completion-at=%s:7:27 %s | FileCheck -check-prefix=CHECK %s +// CHECK: {TypedText iOS} (40) +// CHECK: {TypedText iOSApplicationExtension} (40) +// CHECK: {TypedText macOS} (40) +// CHECK: {TypedText macOSApplicationExtension} (40) +// CHECK: {TypedText tvOS} (40) +// CHECK: {TypedText tvOSApplicationExtension} (40) +// CHECK: {TypedText watchOS} (40) +// CHECK: {TypedText watchOSApplicationExtension} (40) diff --git a/test/Index/get-cursor.m b/test/Index/get-cursor.m index af277d45fdf4..e85d49fb0c3e 100644 --- a/test/Index/get-cursor.m +++ b/test/Index/get-cursor.m @@ -154,6 +154,12 @@ SomeT someVar; typedef MY_TYPE2(SomeT2) { int x; }; SomeT2 someVar2; +#define GEN_DECL(mod_name) __attribute__((external_source_symbol(language="Swift", defined_in=mod_name, generated_declaration))) + +GEN_DECL("some_module") +@interface ExtCls +-(void)method; +@end // RUN: c-index-test -cursor-at=%s:4:28 -cursor-at=%s:5:28 %s | FileCheck -check-prefix=CHECK-PROP %s // CHECK-PROP: ObjCPropertyDecl=foo1:4:26 @@ -226,3 +232,8 @@ SomeT2 someVar2; // CHECK-TRANSPARENT: 147:1 TypeRef=TokenPaste_t:144:9 Extent=[147:1 - 147:13] Spelling=TokenPaste_t ([147:1 - 147:13]) // CHECK-TRANSPARENT: 151:1 TypeRef=SomeT:150:17 (Transparent: struct SomeT) Extent=[151:1 - 151:6] Spelling=SomeT ([151:1 - 151:6]) // CHECK-TRANSPARENT: 155:1 TypeRef=SomeT2:154:18 Extent=[155:1 - 155:7] Spelling=SomeT2 ([155:1 - 155:7]) + +// RUN: c-index-test -cursor-at=%s:160:12 -cursor-at=%s:161:8 %s | FileCheck -check-prefix=CHECK-EXTERNAL %s +// CHECK-EXTERNAL: 160:12 ObjCInterfaceDecl=ExtCls:160:12 (external lang: Swift, defined: some_module, gen: 1) +// CHECK-EXTERNAL: 161:8 ObjCInstanceMethodDecl=method:161:8 (external lang: Swift, defined: some_module, gen: 1) +C \ No newline at end of file diff --git a/test/Misc/warning-flags.c b/test/Misc/warning-flags.c index be02e12e2cbb..5172d3b15a90 100644 --- a/test/Misc/warning-flags.c +++ b/test/Misc/warning-flags.c @@ -6,8 +6,8 @@ This test serves two purposes: (1) It documents all existing warnings that currently have no associated -W flag, and ensures that the list never grows. - If take an existing warning and add a flag, this test will fail. To - fix this test, simply remove that warning from the list below. + If you take an existing warning and add a flag, this test will fail. + To fix this test, simply remove that warning from the list below. (2) It prevents us adding new warnings to Clang that have no -W flag. All new warnings should have -W flags. diff --git a/test/Modules/DebugInfoNamespace.cpp b/test/Modules/DebugInfoNamespace.cpp new file mode 100644 index 000000000000..33add085d8a6 --- /dev/null +++ b/test/Modules/DebugInfoNamespace.cpp @@ -0,0 +1,19 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -x objective-c++ -std=c++11 -debug-info-kind=standalone \ +// RUN: -dwarf-ext-refs -fmodules \ +// RUN: -fmodule-format=obj -fimplicit-module-maps \ +// RUN: -triple %itanium_abi_triple -fmodules-cache-path=%t \ +// RUN: %s -I %S/Inputs/DebugInfoNamespace -I %t -emit-llvm -o - \ +// RUN: | FileCheck %s + +#include "A.h" +#include "B.h" +using namespace N; +B b; + +// Verify that the forward decl of B is in module B. +// +// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "B", +// CHECK-SAME: scope: ![[N:[0-9]+]] +// CHECK: ![[N]] = !DINamespace(name: "N", scope: ![[B:[0-9]+]]) +// CHECK: ![[B]] = !DIModule(scope: null, name: "B", diff --git a/test/Modules/DebugInfoSubmoduleImport.c b/test/Modules/DebugInfoSubmoduleImport.c index 1b31aada9c6a..b608d300d5fe 100644 --- a/test/Modules/DebugInfoSubmoduleImport.c +++ b/test/Modules/DebugInfoSubmoduleImport.c @@ -2,6 +2,11 @@ // RUN: %clang_cc1 -fmodules -fmodule-format=obj -debug-info-kind=limited -dwarf-ext-refs \ // RUN: -fimplicit-module-maps -x c -fmodules-cache-path=%t -I %S/Inputs \ // RUN: %s -emit-llvm -debugger-tuning=lldb -o - | FileCheck %s +// +// RUN: %clang_cc1 -fmodules -fmodule-format=obj -debug-info-kind=limited -dwarf-ext-refs \ +// RUN: -fimplicit-module-maps -x c -fmodules-cache-path=%t -I %S/Inputs \ +// RUN: -fmodules-local-submodule-visibility \ +// RUN: %s -emit-llvm -debugger-tuning=lldb -o - | FileCheck %s #include "DebugSubmoduleA.h" #include "DebugSubmoduleB.h" diff --git a/test/Modules/Inputs/DebugInfoNamespace/A.h b/test/Modules/Inputs/DebugInfoNamespace/A.h new file mode 100644 index 000000000000..dc5a1cd26ab6 --- /dev/null +++ b/test/Modules/Inputs/DebugInfoNamespace/A.h @@ -0,0 +1,3 @@ +namespace N { + struct A {}; +} diff --git a/test/Modules/Inputs/DebugInfoNamespace/B.h b/test/Modules/Inputs/DebugInfoNamespace/B.h new file mode 100644 index 000000000000..c9033a54d4e5 --- /dev/null +++ b/test/Modules/Inputs/DebugInfoNamespace/B.h @@ -0,0 +1,3 @@ +namespace N { + struct B {}; +} diff --git a/test/Modules/Inputs/DebugInfoNamespace/module.modulemap b/test/Modules/Inputs/DebugInfoNamespace/module.modulemap new file mode 100644 index 000000000000..9300fcf98c64 --- /dev/null +++ b/test/Modules/Inputs/DebugInfoNamespace/module.modulemap @@ -0,0 +1,8 @@ +module A { + header "A.h" + export * +} +module B { + header "B.h" + export * +} diff --git a/test/Modules/Inputs/MainA.framework/Frameworks/Sub.framework/Headers/B.h b/test/Modules/Inputs/MainA.framework/Frameworks/Sub.framework/Headers/B.h new file mode 100644 index 000000000000..761540b09cb3 --- /dev/null +++ b/test/Modules/Inputs/MainA.framework/Frameworks/Sub.framework/Headers/B.h @@ -0,0 +1 @@ +// B.h diff --git a/test/Modules/Inputs/MainA.framework/Frameworks/Sub.framework/Headers/Sub.h b/test/Modules/Inputs/MainA.framework/Frameworks/Sub.framework/Headers/Sub.h new file mode 100644 index 000000000000..fd86e3cf872f --- /dev/null +++ b/test/Modules/Inputs/MainA.framework/Frameworks/Sub.framework/Headers/Sub.h @@ -0,0 +1,2 @@ +// Sub.h +#import "B.h" diff --git a/test/Modules/Inputs/MainA.framework/Frameworks/Sub.framework/PrivateHeaders/BPriv.h b/test/Modules/Inputs/MainA.framework/Frameworks/Sub.framework/PrivateHeaders/BPriv.h new file mode 100644 index 000000000000..4ab49b798c63 --- /dev/null +++ b/test/Modules/Inputs/MainA.framework/Frameworks/Sub.framework/PrivateHeaders/BPriv.h @@ -0,0 +1 @@ +// BPriv.h diff --git a/test/Modules/Inputs/MainA.framework/Frameworks/Sub.framework/PrivateHeaders/SubPriv.h b/test/Modules/Inputs/MainA.framework/Frameworks/Sub.framework/PrivateHeaders/SubPriv.h new file mode 100644 index 000000000000..f6ac6188d65f --- /dev/null +++ b/test/Modules/Inputs/MainA.framework/Frameworks/Sub.framework/PrivateHeaders/SubPriv.h @@ -0,0 +1 @@ +#import "BPriv.h" diff --git a/test/Modules/Inputs/MainA.framework/Headers/A.h b/test/Modules/Inputs/MainA.framework/Headers/A.h new file mode 100644 index 000000000000..975f1f0437bb --- /dev/null +++ b/test/Modules/Inputs/MainA.framework/Headers/A.h @@ -0,0 +1 @@ +// A.h diff --git a/test/Modules/Inputs/MainA.framework/Headers/Main.h b/test/Modules/Inputs/MainA.framework/Headers/Main.h new file mode 100644 index 000000000000..cb8cc00a0c45 --- /dev/null +++ b/test/Modules/Inputs/MainA.framework/Headers/Main.h @@ -0,0 +1,2 @@ +// Main.h +#import "A.h" diff --git a/test/Modules/Inputs/MainA.framework/Modules/module.modulemap b/test/Modules/Inputs/MainA.framework/Modules/module.modulemap new file mode 100644 index 000000000000..4b0b5e955386 --- /dev/null +++ b/test/Modules/Inputs/MainA.framework/Modules/module.modulemap @@ -0,0 +1,12 @@ +framework module MainA { + umbrella header "Main.h" + + module * { export * } + export * + + framework module Sub { + umbrella header "Sub.h" + module * { export * } + export * + } +} diff --git a/test/Modules/Inputs/MainA.framework/Modules/module.private.modulemap b/test/Modules/Inputs/MainA.framework/Modules/module.private.modulemap new file mode 100644 index 000000000000..a8dc5c2be5f0 --- /dev/null +++ b/test/Modules/Inputs/MainA.framework/Modules/module.private.modulemap @@ -0,0 +1,12 @@ +framework module MainA_Private { + umbrella header "MainPriv.h" + + module * { export * } + export * + + explicit framework module Sub { + umbrella header "SubPriv.h" + module * { export * } + export * + } +} diff --git a/test/Modules/Inputs/MainA.framework/PrivateHeaders/APriv.h b/test/Modules/Inputs/MainA.framework/PrivateHeaders/APriv.h new file mode 100644 index 000000000000..6ac683c39c55 --- /dev/null +++ b/test/Modules/Inputs/MainA.framework/PrivateHeaders/APriv.h @@ -0,0 +1 @@ +// APriv.h diff --git a/test/Modules/Inputs/MainA.framework/PrivateHeaders/MainPriv.h b/test/Modules/Inputs/MainA.framework/PrivateHeaders/MainPriv.h new file mode 100644 index 000000000000..68103017ad0b --- /dev/null +++ b/test/Modules/Inputs/MainA.framework/PrivateHeaders/MainPriv.h @@ -0,0 +1 @@ +#import "APriv.h" diff --git a/test/Modules/Inputs/SameHeader/A.h b/test/Modules/Inputs/SameHeader/A.h new file mode 100644 index 000000000000..bebe9c31c28e --- /dev/null +++ b/test/Modules/Inputs/SameHeader/A.h @@ -0,0 +1,3 @@ +#ifndef __A_h__ +#define __A_h__ +#endif diff --git a/test/Modules/Inputs/SameHeader/B.h b/test/Modules/Inputs/SameHeader/B.h new file mode 100644 index 000000000000..c3fe49cd854f --- /dev/null +++ b/test/Modules/Inputs/SameHeader/B.h @@ -0,0 +1,4 @@ +#ifndef __B_h__ +#define __B_h__ +#include "C.h" +#endif diff --git a/test/Modules/Inputs/SameHeader/C.h b/test/Modules/Inputs/SameHeader/C.h new file mode 100644 index 000000000000..33c3316a6517 --- /dev/null +++ b/test/Modules/Inputs/SameHeader/C.h @@ -0,0 +1,12 @@ +#ifndef __C_h__ +#define __C_h__ +int c = 1; + +struct aaa { + int b; +}; + +typedef struct fd_set { + char c; +}; +#endif diff --git a/test/Modules/Inputs/SameHeader/module.modulemap b/test/Modules/Inputs/SameHeader/module.modulemap new file mode 100644 index 000000000000..d0283a71ac97 --- /dev/null +++ b/test/Modules/Inputs/SameHeader/module.modulemap @@ -0,0 +1,11 @@ +module X { + module A { + header "A.h" + export * + } + module B { + header "B.h" + export * + } + export * +} diff --git a/test/Modules/find-privateheaders.m b/test/Modules/find-privateheaders.m index c5e82ac70da2..5720a73f9be8 100644 --- a/test/Modules/find-privateheaders.m +++ b/test/Modules/find-privateheaders.m @@ -1,2 +1,13 @@ -// RUN: %clang_cc1 -fmodules -fsyntax-only -F%S/Inputs %s +// RUN: rm -rf %t.cache +// RUN: %clang_cc1 -fmodules -fsyntax-only -F%S/Inputs -fimplicit-module-maps \ +// RUN: -fmodules-cache-path=%t.cache -Wno-private-module -DBUILD_PUBLIC -verify %s +// RUN: rm -rf %t.cache +// RUN: %clang_cc1 -fmodules -fsyntax-only -F%S/Inputs -fimplicit-module-maps \ +// RUN: -fmodules-cache-path=%t.cache -Wno-private-module -verify %s +//expected-no-diagnostics + +#ifdef BUILD_PUBLIC #import "Main/Main.h" +#else +#import "MainA/MainPriv.h" +#endif diff --git a/test/Modules/odr_hash.cpp b/test/Modules/odr_hash.cpp index 294e925627c6..58814dd6b3fb 100644 --- a/test/Modules/odr_hash.cpp +++ b/test/Modules/odr_hash.cpp @@ -1078,6 +1078,39 @@ S s; #endif } +namespace MultipleTypedefs { +#if defined(FIRST) +typedef int B1; +typedef B1 A1; +struct S1 { + A1 x; +}; +#elif defined(SECOND) +typedef int A1; +struct S1 { + A1 x; +}; +#else +S1 s1; +#endif + +#if defined(FIRST) +struct T2 { int x; }; +typedef T2 B2; +typedef B2 A2; +struct S2 { + T2 x; +}; +#elif defined(SECOND) +struct T2 { int x; }; +typedef T2 A2; +struct S2 { + T2 x; +}; +#else +S2 s2; +#endif +} // Keep macros contained to one file. #ifdef FIRST diff --git a/test/Modules/preprocess-module.cpp b/test/Modules/preprocess-module.cpp index a3b789238388..64af00c471df 100644 --- a/test/Modules/preprocess-module.cpp +++ b/test/Modules/preprocess-module.cpp @@ -19,6 +19,11 @@ // RUN: %clang_cc1 -fmodules -fmodule-name=file -fmodule-file=%t/fwd.pcm -x c++-module-map-cpp-output %t/no-rewrite.ii -emit-module -o %t/no-rewrite.pcm // RUN: %clang_cc1 -fmodules -fmodule-name=file -fmodule-file=%t/fwd.pcm -x c++-module-map-cpp-output %t/rewrite.ii -emit-module -o %t/rewrite.pcm +// Check that we can load the original module map in the same compilation (this +// could happen if we had a redundant -fmodule-map-file= in the original +// build). +// RUN: %clang_cc1 -fmodules -fmodule-name=file -fmodule-file=%t/fwd.pcm -fmodule-map-file=%S/Inputs/preprocess/module.modulemap -x c++-module-map-cpp-output %t/rewrite.ii -emit-module -o /dev/null + // Check the module we built works. // RUN: %clang_cc1 -fmodules -fmodule-file=%t/no-rewrite.pcm %s -verify // RUN: %clang_cc1 -fmodules -fmodule-file=%t/rewrite.pcm %s -verify diff --git a/test/Modules/redefinition-same-header.m b/test/Modules/redefinition-same-header.m new file mode 100644 index 000000000000..f1c6cbbcaa2e --- /dev/null +++ b/test/Modules/redefinition-same-header.m @@ -0,0 +1,20 @@ +// RUN: rm -rf %t.tmp +// RUN: %clang_cc1 -fsyntax-only -I %S/Inputs/SameHeader -fmodules \ +// RUN: -fimplicit-module-maps -fmodules-cache-path=%t.tmp %s -verify + +// expected-error@Inputs/SameHeader/C.h:3 {{redefinition of 'c'}} +// expected-note-re@Inputs/SameHeader/B.h:3 {{'{{.*}}C.h' included multiple times, additional include site in header from module 'X.B'}} +// expected-note@Inputs/SameHeader/module.modulemap:6 {{X.B defined here}} +// expected-note-re@redefinition-same-header.m:20 {{'{{.*}}C.h' included multiple times, additional include site here}} + +// expected-error@Inputs/SameHeader/C.h:5 {{redefinition of 'aaa'}} +// expected-note-re@Inputs/SameHeader/B.h:3 {{'{{.*}}C.h' included multiple times, additional include site in header from module 'X.B'}} +// expected-note@Inputs/SameHeader/module.modulemap:6 {{X.B defined here}} +// expected-note-re@redefinition-same-header.m:20 {{'{{.*}}C.h' included multiple times, additional include site here}} + +// expected-error@Inputs/SameHeader/C.h:9 {{redefinition of 'fd_set'}} +// expected-note-re@Inputs/SameHeader/B.h:3 {{'{{.*}}C.h' included multiple times, additional include site in header from module 'X.B'}} +// expected-note@Inputs/SameHeader/module.modulemap:6 {{X.B defined here}} +// expected-note-re@redefinition-same-header.m:20 {{'{{.*}}C.h' included multiple times, additional include site here}} +#include "A.h" // maps to a modular +#include "C.h" // textual include diff --git a/test/OpenMP/report_default_DSA.cpp b/test/OpenMP/report_default_DSA.cpp new file mode 100644 index 000000000000..d14cd5cbe9a4 --- /dev/null +++ b/test/OpenMP/report_default_DSA.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 %s + +void foo(int x, int n) { + double vec[n]; + for (int iter = 0; iter < x; iter++) { +#pragma omp target teams distribute parallel for map( \ + from \ + : vec [0:n]) default(none) + // expected-error@+1 {{variable 'n' must have explicitly specified data sharing attributes}} + for (int ii = 0; ii < n; ii++) { + // expected-error@+3 {{variable 'iter' must have explicitly specified data sharing attributes}} + // expected-error@+2 {{variable 'vec' must have explicitly specified data sharing attributes}} + // expected-error@+1 {{variable 'x' must have explicitly specified data sharing attributes}} + vec[ii] = iter + ii + x; + } + } +} + diff --git a/test/PCH/cxx-templates.cpp b/test/PCH/cxx-templates.cpp index d50eee0623c5..e241701f50df 100644 --- a/test/PCH/cxx-templates.cpp +++ b/test/PCH/cxx-templates.cpp @@ -108,3 +108,11 @@ namespace cyclic_module_load { template int local_extern::f(); // expected-note {{in instantiation of}} #endif template int local_extern::g(); + +namespace MemberSpecializationLocation { +#ifndef NO_ERRORS + // expected-note@cxx-templates.h:* {{previous}} + template<> float A::n; // expected-error {{redeclaration of 'n' with a different type}} +#endif + int k = A::n; +} diff --git a/test/PCH/cxx-templates.h b/test/PCH/cxx-templates.h index c4a844727691..68b252e7974e 100644 --- a/test/PCH/cxx-templates.h +++ b/test/PCH/cxx-templates.h @@ -358,3 +358,6 @@ namespace rdar15468709c { } } +namespace MemberSpecializationLocation { + template struct A { static int n; }; +} diff --git a/test/Parser/objc-available.m b/test/Parser/objc-available.m index a170721240ce..49bc53930655 100644 --- a/test/Parser/objc-available.m +++ b/test/Parser/objc-available.m @@ -21,6 +21,12 @@ void f() { (void)@available; // expected-error{{expected '('}} } +void prettyPlatformNames() { + (void)@available(iOS 8, tvOS 10, watchOS 3, macOS 10.11, *); + (void)__builtin_available(iOSApplicationExtension 8, tvOSApplicationExtension 10, + watchOSApplicationExtension 3, macOSApplicationExtension 10.11, *); +} + #if __has_builtin(__builtin_available) #error expected // expected-error@-1 {{expected}} diff --git a/test/Preprocessor/predefined-arch-macros.c b/test/Preprocessor/predefined-arch-macros.c index a0eb8cbcca9a..08f4d2573f40 100644 --- a/test/Preprocessor/predefined-arch-macros.c +++ b/test/Preprocessor/predefined-arch-macros.c @@ -1601,6 +1601,7 @@ // CHECK_BDVER1_M32: #define __AES__ 1 // CHECK_BDVER1_M32: #define __AVX__ 1 // CHECK_BDVER1_M32: #define __FMA4__ 1 +// CHECK_BDVER1_M32: #define __LWP__ 1 // CHECK_BDVER1_M32: #define __LZCNT__ 1 // CHECK_BDVER1_M32: #define __MMX__ 1 // CHECK_BDVER1_M32: #define __PCLMUL__ 1 @@ -1630,6 +1631,7 @@ // CHECK_BDVER1_M64: #define __AES__ 1 // CHECK_BDVER1_M64: #define __AVX__ 1 // CHECK_BDVER1_M64: #define __FMA4__ 1 +// CHECK_BDVER1_M64: #define __LWP__ 1 // CHECK_BDVER1_M64: #define __LZCNT__ 1 // CHECK_BDVER1_M64: #define __MMX__ 1 // CHECK_BDVER1_M64: #define __PCLMUL__ 1 @@ -1664,6 +1666,7 @@ // CHECK_BDVER2_M32: #define __F16C__ 1 // CHECK_BDVER2_M32: #define __FMA4__ 1 // CHECK_BDVER2_M32: #define __FMA__ 1 +// CHECK_BDVER2_M32: #define __LWP__ 1 // CHECK_BDVER2_M32: #define __LZCNT__ 1 // CHECK_BDVER2_M32: #define __MMX__ 1 // CHECK_BDVER2_M32: #define __PCLMUL__ 1 @@ -1697,6 +1700,7 @@ // CHECK_BDVER2_M64: #define __F16C__ 1 // CHECK_BDVER2_M64: #define __FMA4__ 1 // CHECK_BDVER2_M64: #define __FMA__ 1 +// CHECK_BDVER2_M64: #define __LWP__ 1 // CHECK_BDVER2_M64: #define __LZCNT__ 1 // CHECK_BDVER2_M64: #define __MMX__ 1 // CHECK_BDVER2_M64: #define __PCLMUL__ 1 @@ -1733,6 +1737,7 @@ // CHECK_BDVER3_M32: #define __FMA4__ 1 // CHECK_BDVER3_M32: #define __FMA__ 1 // CHECK_BDVER3_M32: #define __FSGSBASE__ 1 +// CHECK_BDVER3_M32: #define __LWP__ 1 // CHECK_BDVER3_M32: #define __LZCNT__ 1 // CHECK_BDVER3_M32: #define __MMX__ 1 // CHECK_BDVER3_M32: #define __PCLMUL__ 1 @@ -1768,6 +1773,7 @@ // CHECK_BDVER3_M64: #define __FMA4__ 1 // CHECK_BDVER3_M64: #define __FMA__ 1 // CHECK_BDVER3_M64: #define __FSGSBASE__ 1 +// CHECK_BDVER3_M64: #define __LWP__ 1 // CHECK_BDVER3_M64: #define __LZCNT__ 1 // CHECK_BDVER3_M64: #define __MMX__ 1 // CHECK_BDVER3_M64: #define __PCLMUL__ 1 @@ -1807,6 +1813,7 @@ // CHECK_BDVER4_M32: #define __FMA4__ 1 // CHECK_BDVER4_M32: #define __FMA__ 1 // CHECK_BDVER4_M32: #define __FSGSBASE__ 1 +// CHECK_BDVER4_M32: #define __LWP__ 1 // CHECK_BDVER4_M32: #define __LZCNT__ 1 // CHECK_BDVER4_M32: #define __MMX__ 1 // CHECK_BDVER4_M32: #define __PCLMUL__ 1 @@ -1843,6 +1850,7 @@ // CHECK_BDVER4_M64: #define __FMA4__ 1 // CHECK_BDVER4_M64: #define __FMA__ 1 // CHECK_BDVER4_M64: #define __FSGSBASE__ 1 +// CHECK_BDVER4_M64: #define __LWP__ 1 // CHECK_BDVER4_M64: #define __LZCNT__ 1 // CHECK_BDVER4_M64: #define __MMX__ 1 // CHECK_BDVER4_M64: #define __PCLMUL__ 1 diff --git a/test/Preprocessor/x86_target_features.c b/test/Preprocessor/x86_target_features.c index a201900ba762..ce3835f91f42 100644 --- a/test/Preprocessor/x86_target_features.c +++ b/test/Preprocessor/x86_target_features.c @@ -272,6 +272,14 @@ // AESNOSSE2-NOT: #define __SSE2__ 1 // AESNOSSE2-NOT: #define __SSE3__ 1 +// RUN: %clang -target i386-unknown-unknown -march=pentiumpro -mlwp -x c -E -dM -o - %s | FileCheck -match-full-lines --check-prefix=LWP %s + +// LWP: #define __LWP__ 1 + +// RUN: %clang -target i386-unknown-unknown -march=bdver1 -mno-lwp -x c -E -dM -o - %s | FileCheck -match-full-lines --check-prefix=NOLWP %s + +// NOLWP-NOT: #define __LWP__ 1 + // RUN: %clang -target i386-unknown-unknown -march=pentiumpro -msha -x c -E -dM -o - %s | FileCheck -match-full-lines --check-prefix=SHA %s // SHA: #define __SHA__ 1 diff --git a/test/Sema/overloadable.c b/test/Sema/overloadable.c index f5e17d211910..49d8085651d4 100644 --- a/test/Sema/overloadable.c +++ b/test/Sema/overloadable.c @@ -151,3 +151,18 @@ void dropping_qualifiers_is_incompatible() { foo(ccharbuf); // expected-error{{call to 'foo' is ambiguous}} expected-note@148{{candidate function}} expected-note@149{{candidate function}} foo(vcharbuf); // expected-error{{call to 'foo' is ambiguous}} expected-note@148{{candidate function}} expected-note@149{{candidate function}} } + +// Bug: we used to treat `__typeof__(foo)` as though it was `__typeof__(&foo)` +// if `foo` was overloaded with only one function that could have its address +// taken. +void typeof_function_is_not_a_pointer() { + void not_a_pointer(void *) __attribute__((overloadable)); + void not_a_pointer(char *__attribute__((pass_object_size(1)))) + __attribute__((overloadable)); + + __typeof__(not_a_pointer) *fn; + + void take_fn(void (*)(void *)); + // if take_fn is passed a void (**)(void *), we'll get a warning. + take_fn(fn); +} diff --git a/test/Sema/redefinition-same-header.c b/test/Sema/redefinition-same-header.c new file mode 100644 index 000000000000..be5bd1d71c92 --- /dev/null +++ b/test/Sema/redefinition-same-header.c @@ -0,0 +1,14 @@ +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: echo 'int yyy = 42;' > %t/a.h +// RUN: %clang_cc1 -fsyntax-only %s -I%t -verify + +// expected-error@a.h:1 {{redefinition of 'yyy'}} +// expected-note@a.h:1 {{unguarded header; consider using #ifdef guards or #pragma once}} +// expected-note-re@redefinition-same-header.c:11 {{'{{.*}}a.h' included multiple times, additional include site here}} +// expected-note-re@redefinition-same-header.c:12 {{'{{.*}}a.h' included multiple times, additional include site here}} + +#include "a.h" +#include "a.h" + +int foo() { return yyy; } diff --git a/test/Sema/typo-correction.c b/test/Sema/typo-correction.c index 59f022dfe528..78007015dcae 100644 --- a/test/Sema/typo-correction.c +++ b/test/Sema/typo-correction.c @@ -80,3 +80,10 @@ int h() { g(x, 5 ? z : 0); // expected-error 2 {{use of undeclared identifier}} (x, 5 ? z : 0); // expected-error 2 {{use of undeclared identifier}} } + +__attribute__((overloadable)) void func_overloadable(int); +__attribute__((overloadable)) void func_overloadable(float); + +void overloadable_callexpr(int arg) { + func_overloadable(ar); //expected-error{{use of undeclared identifier}} +} diff --git a/test/Sema/vector-cast.c b/test/Sema/vector-cast.c index ea4acfac6a0b..cf23eb2742c4 100644 --- a/test/Sema/vector-cast.c +++ b/test/Sema/vector-cast.c @@ -53,9 +53,8 @@ void f4() { float2 f2; double d, a, b, c; float64x2_t v = {0.0, 1.0}; - // FIXME: These diagnostics are inaccurate: should complain that 'double' to vector 'float2' involves truncation - f2 += d; // expected-error {{cannot convert between vector values of different size ('float2' (vector of 2 'float' values) and 'double')}} - d += f2; // expected-error {{cannot convert between vector values of different size}} + f2 += d; // expected-error {{cannot convert between scalar type 'double' and vector type 'float2' (vector of 2 'float' values) as implicit conversion would cause truncation}} + d += f2; // expected-error {{assigning to 'double' from incompatible type 'float2' (vector of 2 'float' values)}} a = 3.0 + vget_low_f64(v); b = vget_low_f64(v) + 3.0; c = vget_low_f64(v); diff --git a/test/Sema/vector-gcc-compat.c b/test/Sema/vector-gcc-compat.c new file mode 100644 index 000000000000..9eb0569b25f0 --- /dev/null +++ b/test/Sema/vector-gcc-compat.c @@ -0,0 +1,330 @@ +// RUN: %clang_cc1 %s -verify -fsyntax-only -Weverything -triple x86_64-apple-darwin10 + +// Test the compatibility of clang's vector extensions with gcc's vector +// extensions for C. Notably &&, ||, ?: and ! are not available. +typedef long long v2i64 __attribute__((vector_size(16))); +typedef int v2i32 __attribute__((vector_size(8))); +typedef short v2i16 __attribute__((vector_size(4))); +typedef char v2i8 __attribute__((vector_size(2))); + +typedef unsigned long long v2u64 __attribute__((vector_size(16))); +typedef unsigned int v2u32 __attribute__((vector_size(8))); +typedef unsigned short v2u16 __attribute__((vector_size(4))); +typedef unsigned char v2u8 __attribute__((vector_size(2))); + +typedef float v4f32 __attribute__((vector_size(16))); +typedef double v2f64 __attribute__((vector_size(16))); +typedef double v4f64 __attribute__((vector_size(32))); +typedef int v4i32 __attribute((vector_size(16))); + +void arithmeticTest(void); +void logicTest(void); +void comparisonTest(void); +void floatTestSignedType(char a, short b, int c, long long d); +void floatTestUnsignedType(unsigned char a, unsigned short b, unsigned int c, + unsigned long long d); +void floatTestConstant(void); +void intTestType(char a, short b, int c, long long d); +void intTestTypeUnsigned(unsigned char a, unsigned short b, unsigned int c, + unsigned long long d); +void uintTestType(char a, short b, int c, long long d); +void uintTestTypeUnsigned(unsigned char a, unsigned short b, unsigned int c, + unsigned long long d); +void uintTestConstant(v2u64 v2u64_a, v2u32 v2u32_a, v2u16 v2u16_a, v2u8 v2u8_a); +void intTestConstant(v2i64 v2i64_a, v2i32 v2i32_a, v2i16 v2i16_a, v2i8 v2i8_a); + +void arithmeticTest(void) { + v2i64 v2i64_a = (v2i64){0, 1}; + v2i64 v2i64_r; + + v2i64_r = v2i64_a + 1; + v2i64_r = v2i64_a - 1; + v2i64_r = v2i64_a * 1; + v2i64_r = v2i64_a / 1; + v2i64_r = v2i64_a % 1; + + v2i64_r = 1 + v2i64_a; + v2i64_r = 1 - v2i64_a; + v2i64_r = 1 * v2i64_a; + v2i64_r = 1 / v2i64_a; + v2i64_r = 1 % v2i64_a; + + v2i64_a += 1; + v2i64_a -= 1; + v2i64_a *= 1; + v2i64_a /= 1; + v2i64_a %= 1; +} + +void comparisonTest(void) { + v2i64 v2i64_a = (v2i64){0, 1}; + v2i64 v2i64_r; + + v2i64_r = v2i64_a == 1; + v2i64_r = v2i64_a != 1; + v2i64_r = v2i64_a < 1; + v2i64_r = v2i64_a > 1; + v2i64_r = v2i64_a <= 1; + v2i64_r = v2i64_a >= 1; + + v2i64_r = 1 == v2i64_a; + v2i64_r = 1 != v2i64_a; + v2i64_r = 1 < v2i64_a; + v2i64_r = 1 > v2i64_a; + v2i64_r = 1 <= v2i64_a; + v2i64_r = 1 >= v2i64_a; +} + +void logicTest(void) { + v2i64 v2i64_a = (v2i64){0, 1}; + v2i64 v2i64_b = (v2i64){2, 1}; + v2i64 v2i64_c = (v2i64){3, 1}; + v2i64 v2i64_r; + + v2i64_r = !v2i64_a; // expected-error {{invalid argument type 'v2i64' (vector of 2 'long long' values) to unary expression}} + v2i64_r = ~v2i64_a; + + v2i64_r = v2i64_a ? v2i64_b : v2i64_c; // expected-error {{used type 'v2i64' (vector of 2 'long long' values) where arithmetic or pointer type is required}} + + v2i64_r = v2i64_a & 1; + v2i64_r = v2i64_a | 1; + v2i64_r = v2i64_a ^ 1; + + v2i64_r = 1 & v2i64_a; + v2i64_r = 1 | v2i64_a; + v2i64_r = 1 ^ v2i64_a; + + v2i64_a &= 1; + v2i64_a |= 1; + v2i64_a ^= 1; + + v2i64_r = v2i64_a && 1; // expected-error {{logical expression with vector type 'v2i64' (vector of 2 'long long' values) and non-vector type 'int' is only supported in C++}} + v2i64_r = v2i64_a || 1; // expected-error {{logical expression with vector type 'v2i64' (vector of 2 'long long' values) and non-vector type 'int' is only supported in C++}} + + v2i64_r = v2i64_a && v2i64_a; // expected-error {{logical expression with vector types 'v2i64' (vector of 2 'long long' values) and 'v2i64' is only supported in C++}} + v2i64_r = v2i64_a || v2i64_a; // expected-error {{logical expression with vector types 'v2i64' (vector of 2 'long long' values) and 'v2i64' is only supported in C++}} + + v2i64_r = v2i64_a << 1; + v2i64_r = v2i64_a >> 1; + + v2i64_r = 1 << v2i64_a; + v2i64_r = 1 >> v2i64_a; + + v2i64_a <<= 1; + v2i64_a >>= 1; +} + +// For operations with floating point types, we check that interger constants +// can be respresented, or failing that checking based on the integer types. +void floatTestConstant(void) { + // Test that constants added to floats must be expressible as floating point + // numbers. + v4f32 v4f32_a = {0.4f, 0.4f, 0.4f, 0.4f}; + v4f32_a = v4f32_a + 1; + v4f32_a = v4f32_a + 0xFFFFFF; + v4f32_a = v4f32_a + (-1567563LL); + v4f32_a = v4f32_a + (16777208); + v4f32_a = v4f32_a + (16777219); // expected-error {{cannot convert between scalar type 'int' and vector type 'v4f32' (vector of 4 'float' values) as implicit conversion would cause truncation}} +} + +void floatTestConstantComparison(void); +void doubleTestConstantComparison(void); + +void floatTestConstantComparison(void) { + v4f32 v4f32_a = {0.4f, 0.4f, 0.4f, 0.4f}; + v4i32 v4i32_r; + v4i32_r = v4f32_a > 0.4f; + v4i32_r = v4f32_a >= 0.4f; + v4i32_r = v4f32_a < 0.4f; + v4i32_r = v4f32_a <= 0.4f; + v4i32_r = v4f32_a == 0.4f; // expected-warning {{comparing floating point with == or != is unsafe}} + v4i32_r = v4f32_a != 0.4f; // expected-warning {{comparing floating point with == or != is unsafe}} +} + +void doubleTestConstantComparison(void) { + v2f64 v2f64_a = {0.4, 0.4}; + v2i64 v2i64_r; + v2i64_r = v2f64_a > 0.4; + v2i64_r = v2f64_a >= 0.4; + v2i64_r = v2f64_a < 0.4; + v2i64_r = v2f64_a <= 0.4; + v2i64_r = v2f64_a == 0.4; // expected-warning {{comparing floating point with == or != is unsafe}} + v2i64_r = v2f64_a != 0.4; // expected-warning {{comparing floating point with == or != is unsafe}} +} + +void floatTestUnsignedType(unsigned char a, unsigned short b, unsigned int c, + unsigned long long d) { + v4f32 v4f32_a = {0.4f, 0.4f, 0.4f, 0.4f}; + v4f64 v4f64_b = {0.4, 0.4, 0.4, 0.4}; + + v4f32_a = v4f32_a + a; + v4f32_a = v4f32_a + b; + v4f32_a = v4f32_a + c; // expected-error {{cannot convert between scalar type 'unsigned int' and vector type 'v4f32' (vector of 4 'float' values) as implicit conversion would cause truncation}} + v4f32_a = v4f32_a + d; // expected-error {{cannot convert between scalar type 'unsigned long long' and vector type 'v4f32' (vector of 4 'float' values) as implicit conversion would cause truncation}} + + v4f64_b = v4f64_b + a; + v4f64_b = v4f64_b + b; + v4f64_b = v4f64_b + c; + v4f64_b = v4f64_b + d; // expected-error {{cannot convert between scalar type 'unsigned long long' and vector type 'v4f64' (vector of 4 'double' values) as implicit conversion would cause truncation}} +} + +void floatTestSignedType(char a, short b, int c, long long d) { + v4f32 v4f32_a = {0.4f, 0.4f, 0.4f, 0.4f}; + v4f64 v4f64_b = {0.4, 0.4, 0.4, 0.4}; + + v4f32_a = v4f32_a + a; + v4f32_a = v4f32_a + b; + v4f32_a = v4f32_a + c; // expected-error {{cannot convert between scalar type 'int' and vector type 'v4f32' (vector of 4 'float' values) as implicit conversion would cause truncation}} + v4f32_a = v4f32_a + d; // expected-error {{cannot convert between scalar type 'long long' and vector type 'v4f32' (vector of 4 'float' values) as implicit conversion would cause truncation}} + + v4f64_b = v4f64_b + a; + v4f64_b = v4f64_b + b; + v4f64_b = v4f64_b + c; + v4f64_b = v4f64_b + d; // expected-error {{cannot convert between scalar type 'long long' and vector type 'v4f64' (vector of 4 'double' values) as implicit conversion would cause truncation}} +} + +void intTestType(char a, short b, int c, long long d) { + v2i64 v2i64_a = {1, 2}; + v2i32 v2i32_a = {1, 2}; + v2i16 v2i16_a = {1, 2}; + v2i8 v2i8_a = {1, 2}; + + v2i64_a = v2i64_a + d; + v2i64_a = v2i64_a + c; + v2i64_a = v2i64_a + b; + v2i64_a = v2i64_a + a; + + v2i32_a = v2i32_a + d; // expected-warning {{implicit conversion loses integer precision: 'long long' to 'v2i32' (vector of 2 'int' values)}} + v2i32_a = v2i32_a + c; + v2i32_a = v2i32_a + b; + v2i32_a = v2i32_a + a; + + v2i16_a = v2i16_a + d; // expected-error {{cannot convert between scalar type 'long long' and vector type 'v2i16' (vector of 2 'short' values) as implicit conversion would cause truncation}} + v2i16_a = v2i16_a + c; // expected-warning {{implicit conversion loses integer precision: 'int' to 'v2i16' (vector of 2 'short' values)}} + v2i16_a = v2i16_a + b; + v2i16_a = v2i16_a + a; + + v2i8_a = v2i8_a + d; // expected-error {{cannot convert between scalar type 'long long' and vector type 'v2i8' (vector of 2 'char' values) as implicit conversion would cause truncation}} + v2i8_a = v2i8_a + c; // expected-error {{cannot convert between scalar type 'int' and vector type 'v2i8' (vector of 2 'char' values) as implicit conversion would cause truncation}} + v2i8_a = v2i8_a + b; // expected-warning {{implicit conversion loses integer precision: 'short' to 'v2i8' (vector of 2 'char' values)}} + v2i8_a = v2i8_a + a; +} + +void intTestTypeUnsigned(unsigned char a, unsigned short b, unsigned int c, + unsigned long long d) { + v2i64 v2i64_a = {1, 2}; + v2i32 v2i32_a = {1, 2}; + v2i16 v2i16_a = {1, 2}; + v2i8 v2i8_a = {1, 2}; + + v2i64_a = v2i64_a + d; // expected-error {{cannot convert between scalar type 'unsigned long long' and vector type 'v2i64' (vector of 2 'long long' values) as implicit conversion would cause truncation}} + + v2i64_a = v2i64_a + c; + v2i64_a = v2i64_a + b; + v2i64_a = v2i64_a + a; + + v2i32_a = v2i32_a + d; // expected-warning {{implicit conversion loses integer precision: 'unsigned long long' to 'v2i32' (vector of 2 'int' values)}} + v2i32_a = v2i32_a + c; // expected-error {{cannot convert between scalar type 'unsigned int' and vector type 'v2i32' (vector of 2 'int' values) as implicit conversion would cause truncation}} + v2i32_a = v2i32_a + b; + v2i32_a = v2i32_a + a; + + v2i16_a = v2i16_a + d; // expected-error {{cannot convert between scalar type 'unsigned long long' and vector type 'v2i16' (vector of 2 'short' values) as implicit conversion would cause truncation}} + v2i16_a = v2i16_a + c; // expected-warning {{implicit conversion loses integer precision: 'unsigned int' to 'v2i16' (vector of 2 'short' values)}} + v2i16_a = v2i16_a + b; // expected-error {{cannot convert between scalar type 'unsigned short' and vector type 'v2i16' (vector of 2 'short' values) as implicit conversion would cause truncation}} + v2i16_a = v2i16_a + a; + + v2i8_a = v2i8_a + d; // expected-error {{cannot convert between scalar type 'unsigned long long' and vector type 'v2i8' (vector of 2 'char' values) as implicit conversion would cause truncation}} + v2i8_a = v2i8_a + c; // expected-error {{cannot convert between scalar type 'unsigned int' and vector type 'v2i8' (vector of 2 'char' values) as implicit conversion would cause truncation}} + v2i8_a = v2i8_a + b; // expected-warning {{implicit conversion loses integer precision: 'unsigned short' to 'v2i8' (vector of 2 'char' values)}} + v2i8_a = v2i8_a + a; // expected-error {{cannot convert between scalar type 'unsigned char' and vector type 'v2i8' (vector of 2 'char' values) as implicit conversion would cause truncation}} +} + +void uintTestType(char a, short b, int c, long long d) { + v2u64 v2u64_a = {1, 2}; + v2u32 v2u32_a = {1, 2}; + v2u16 v2u16_a = {1, 2}; + v2u8 v2u8_a = {1, 2}; + + v2u64_a = v2u64_a + d; // expected-warning {{implicit conversion changes signedness: 'long long' to 'v2u64' (vector of 2 'unsigned long long' values)}} + v2u64_a = v2u64_a + c; // expected-warning {{implicit conversion changes signedness: 'int' to 'v2u64' (vector of 2 'unsigned long long' values)}} + v2u64_a = v2u64_a + b; // expected-warning {{implicit conversion changes signedness: 'short' to 'v2u64' (vector of 2 'unsigned long long' values)}} + v2u64_a = v2u64_a + a; // expected-warning {{implicit conversion changes signedness: 'char' to 'v2u64' (vector of 2 'unsigned long long' values)}} + + v2u32_a = v2u32_a + d; // expected-warning {{implicit conversion loses integer precision: 'long long' to 'v2u32' (vector of 2 'unsigned int' values)}} + v2u32_a = v2u32_a + c; // expected-warning {{implicit conversion changes signedness: 'int' to 'v2u32' (vector of 2 'unsigned int' values)}} + v2u32_a = v2u32_a + b; // expected-warning {{implicit conversion changes signedness: 'short' to 'v2u32' (vector of 2 'unsigned int' values)}} + v2u32_a = v2u32_a + a; // expected-warning {{implicit conversion changes signedness: 'char' to 'v2u32' (vector of 2 'unsigned int' values)}} + + v2u16_a = v2u16_a + d; // expected-error {{cannot convert between scalar type 'long long' and vector type 'v2u16' (vector of 2 'unsigned short' values) as implicit conversion would cause truncation}} + v2u16_a = v2u16_a + c; // expected-warning {{implicit conversion loses integer precision: 'int' to 'v2u16' (vector of 2 'unsigned short' values)}} + v2u16_a = v2u16_a + b; // expected-warning {{implicit conversion changes signedness: 'short' to 'v2u16' (vector of 2 'unsigned short' values)}} + v2u16_a = v2u16_a + a; // expected-warning {{implicit conversion changes signedness: 'char' to 'v2u16' (vector of 2 'unsigned short' values)}} + + v2u8_a = v2u8_a + d; // expected-error {{cannot convert between scalar type 'long long' and vector type 'v2u8' (vector of 2 'unsigned char' values) as implicit conversion would cause truncation}} + v2u8_a = v2u8_a + c; // expected-error {{cannot convert between scalar type 'int' and vector type 'v2u8' (vector of 2 'unsigned char' values) as implicit conversion would cause truncation}} + v2u8_a = v2u8_a + b; // expected-warning {{implicit conversion loses integer precision: 'short' to 'v2u8' (vector of 2 'unsigned char' values)}} + v2u8_a = v2u8_a + a; // expected-warning {{implicit conversion changes signedness: 'char' to 'v2u8' (vector of 2 'unsigned char' values)}} +} + +void uintTestTypeUnsigned(unsigned char a, unsigned short b, unsigned int c, + unsigned long long d) { + v2u64 v2u64_a = {1, 2}; + v2u32 v2u32_a = {1, 2}; + v2u16 v2u16_a = {1, 2}; + v2u8 v2u8_a = {1, 2}; + + v2u64_a = v2u64_a + d; + v2u64_a = v2u64_a + c; + v2u64_a = v2u64_a + b; + v2u64_a = v2u64_a + a; + + v2u32_a = v2u32_a + d; // expected-warning {{implicit conversion loses integer precision: 'unsigned long long' to 'v2u32' (vector of 2 'unsigned int' values)}} + v2u32_a = v2u32_a + c; + v2u32_a = v2u32_a + b; + v2u32_a = v2u32_a + a; + + v2u16_a = v2u16_a + d; // expected-error {{cannot convert between scalar type 'unsigned long long' and vector type 'v2u16' (vector of 2 'unsigned short' values) as implicit conversion would cause truncation}} + v2u16_a = v2u16_a + c; // expected-warning {{implicit conversion loses integer precision: 'unsigned int' to 'v2u16' (vector of 2 'unsigned short' values)}} + v2u16_a = v2u16_a + b; + v2u16_a = v2u16_a + a; + + v2u8_a = v2u8_a + d; // expected-error {{cannot convert between scalar type 'unsigned long long' and vector type 'v2u8' (vector of 2 'unsigned char' values) as implicit conversion would cause truncation}} + v2u8_a = v2u8_a + c; // expected-error {{cannot convert between scalar type 'unsigned int' and vector type 'v2u8' (vector of 2 'unsigned char' values) as implicit conversion would cause truncation}} + v2u8_a = v2u8_a + b; // expected-warning {{implicit conversion loses integer precision: 'unsigned short' to 'v2u8' (vector of 2 'unsigned char' values)}} + v2u8_a = v2u8_a + a; +} + +void uintTestConstant(v2u64 v2u64_a, v2u32 v2u32_a, v2u16 v2u16_a, + v2u8 v2u8_a) { + v2u64_a = v2u64_a + 0xFFFFFFFFFFFFFFFF; + v2u32_a = v2u32_a + 0xFFFFFFFF; + v2u16_a = v2u16_a + 0xFFFF; + v2u8_a = v2u8_a + 0xFF; + + v2u32_a = v2u32_a + 0x1FFFFFFFF; // expected-warning {{implicit conversion from 'long' to 'v2u32' (vector of 2 'unsigned int' values) changes value from 8589934591 to 4294967295}} + v2u16_a = v2u16_a + 0x1FFFF; // expected-warning {{implicit conversion from 'int' to 'v2u16' (vector of 2 'unsigned short' values) changes value from 131071 to 65535}} + v2u8_a = v2u8_a + 0x1FF; // expected-error {{cannot convert between scalar type 'int' and vector type 'v2u8' (vector of 2 'unsigned char' values) as implicit conversion would cause truncation}} +} + +void intTestConstant(v2i64 v2i64_a, v2i32 v2i32_a, v2i16 v2i16_a, v2i8 v2i8_a) { + // Legal upper bounds. + v2i64_a = v2i64_a + (long long)0x7FFFFFFFFFFFFFFF; + v2i32_a = v2i32_a + (int)0x7FFFFFFF; + v2i16_a = v2i16_a + (short)0x7FFF; + v2i8_a = v2i8_a + (char)0x7F; + + // Legal lower bounds. + v2i64_a = v2i64_a + (-9223372036854775807); + v2i32_a = v2i32_a + (-2147483648); + v2i16_a = v2i16_a + (-32768); + v2i8_a = v2i8_a + (-128); + + // One increment/decrement more than the type can hold + v2i32_a = v2i32_a + 2147483648; // expected-warning {{implicit conversion from 'long' to 'v2i32' (vector of 2 'int' values) changes value from 2147483648 to -2147483648}} + v2i16_a = v2i16_a + 32768; // expected-warning {{implicit conversion from 'int' to 'v2i16' (vector of 2 'short' values) changes value from 32768 to -32768}} + v2i8_a = v2i8_a + 128; // expected-warning {{implicit conversion from 'int' to 'v2i8' (vector of 2 'char' values) changes value from 128 to -128}} + + v2i32_a = v2i32_a + (-2147483649); // expected-warning {{implicit conversion from 'long' to 'v2i32' (vector of 2 'int' values) changes value from -2147483649 to 2147483647}} + v2i16_a = v2i16_a + (-32769); // expected-warning {{implicit conversion from 'int' to 'v2i16' (vector of 2 'short' values) changes value from -32769 to 32767}} + v2i8_a = v2i8_a + (-129); // expected-error {{cannot convert between scalar type 'int' and vector type 'v2i8' (vector of 2 'char' values) as implicit conversion would cause truncation}} +} diff --git a/test/Sema/vector-gcc-compat.cpp b/test/Sema/vector-gcc-compat.cpp new file mode 100644 index 000000000000..12da314c325f --- /dev/null +++ b/test/Sema/vector-gcc-compat.cpp @@ -0,0 +1,328 @@ +// RUN: %clang_cc1 %s -verify -fsyntax-only -Weverything -std=c++11 -triple x86_64-apple-darwin10 + +// Test the compatibility of clang++'s vector extensions with g++'s vector +// extensions. In comparison to the extensions available in C, the !, ?:, && and +// || operators work on vector types. + +typedef long long v2i64 __attribute__((vector_size(16))); // expected-warning {{'long long' is incompatible with C++98}} +typedef int v2i32 __attribute__((vector_size(8))); +typedef short v2i16 __attribute__((vector_size(4))); +typedef char v2i8 __attribute__((vector_size(2))); + +typedef unsigned long long v2u64 __attribute__((vector_size(16))); // expected-warning {{'long long' is incompatible with C++98}} +typedef unsigned int v2u32 __attribute__((vector_size(8))); +typedef unsigned short v2u16 __attribute__((vector_size(4))); +typedef unsigned char v2u8 __attribute__((vector_size(2))); + +typedef float v4f32 __attribute__((vector_size(16))); +typedef double v2f64 __attribute__((vector_size(16))); +typedef double v4f64 __attribute__((vector_size(32))); +typedef int v4i32 __attribute((vector_size(16))); + +void arithmeticTest(void); +void logicTest(void); +void comparisonTest(void); +void floatTestSignedType(char a, short b, int c, long long d); // expected-warning {{'long long' is incompatible with C++98}} +void floatTestUnsignedType(unsigned char a, unsigned short b, unsigned int c, + unsigned long long d); // expected-warning {{'long long' is incompatible with C++98}} +void floatTestConstant(void); +void intTestType(char a, short b, int c, long long d); // expected-warning {{'long long' is incompatible with C++98}} +void intTestTypeUnsigned(unsigned char a, unsigned short b, unsigned int c, + unsigned long long d); // expected-warning {{'long long' is incompatible with C++98}} +void uintTestType(char a, short b, int c, long long d); // expected-warning {{'long long' is incompatible with C++98}} +void uintTestTypeUnsigned(unsigned char a, unsigned short b, unsigned int c, + unsigned long long d); // expected-warning {{'long long' is incompatible with C++98}} +void uintTestConstant(v2u64 v2u64_a, v2u32 v2u32_a, v2u16 v2u16_a, v2u8 v2u8_a); +void intTestConstant(v2i64 v2i64_a, v2i32 v2i32_a, v2i16 v2i16_a, v2i8 v2i8_a); + +void arithmeticTest(void) { + v2i64 v2i64_a = (v2i64){0, 1}; // expected-warning {{compound literals are a C99-specific feature}} + v2i64 v2i64_r; + + v2i64_r = v2i64_a + 1; + v2i64_r = v2i64_a - 1; + v2i64_r = v2i64_a * 1; + v2i64_r = v2i64_a / 1; + v2i64_r = v2i64_a % 1; + + v2i64_r = 1 + v2i64_a; + v2i64_r = 1 - v2i64_a; + v2i64_r = 1 * v2i64_a; + v2i64_r = 1 / v2i64_a; + v2i64_r = 1 % v2i64_a; + + v2i64_a += 1; + v2i64_a -= 1; + v2i64_a *= 1; + v2i64_a /= 1; + v2i64_a %= 1; +} + +void comparisonTest(void) { + v2i64 v2i64_a = (v2i64){0, 1}; // expected-warning {{compound literals are a C99-specific feature}} + v2i64 v2i64_r; + + v2i64_r = v2i64_a == 1; + v2i64_r = v2i64_a != 1; + v2i64_r = v2i64_a < 1; + v2i64_r = v2i64_a > 1; + v2i64_r = v2i64_a <= 1; + v2i64_r = v2i64_a >= 1; + + v2i64_r = 1 == v2i64_a; + v2i64_r = 1 != v2i64_a; + v2i64_r = 1 < v2i64_a; + v2i64_r = 1 > v2i64_a; + v2i64_r = 1 <= v2i64_a; + v2i64_r = 1 >= v2i64_a; +} + +void logicTest(void) { + v2i64 v2i64_a = (v2i64){0, 1}; // expected-warning {{compound literals are a C99-specific feature}} + v2i64 v2i64_b = (v2i64){2, 1}; // expected-warning {{compound literals are a C99-specific feature}} + v2i64 v2i64_c = (v2i64){3, 1}; // expected-warning {{compound literals are a C99-specific feature}} + v2i64 v2i64_r; + + v2i64_r = !v2i64_a; // expected-error {{invalid argument type 'v2i64' (vector of 2 'long long' values) to unary expression}} + v2i64_r = ~v2i64_a; + + v2i64_r = v2i64_a ? v2i64_b : v2i64_c; // expected-error {{value of type 'v2i64' (vector of 2 'long long' values) is not contextually convertible to 'bool'}} + + v2i64_r = v2i64_a & 1; + v2i64_r = v2i64_a | 1; + v2i64_r = v2i64_a ^ 1; + + v2i64_r = 1 & v2i64_a; + v2i64_r = 1 | v2i64_a; + v2i64_r = 1 ^ v2i64_a; + v2i64_a &= 1; + v2i64_a |= 1; + v2i64_a ^= 1; + + v2i64_r = v2i64_a && 1; + v2i64_r = v2i64_a || 1; + + v2i64_r = v2i64_a << 1; + v2i64_r = v2i64_a >> 1; + + v2i64_r = 1 << v2i64_a; + v2i64_r = 1 >> v2i64_a; + + v2i64_a <<= 1; + v2i64_a >>= 1; +} + +// For operations with floating point types, we check that interger constants +// can be respresented, or failing that checking based on the integer types. +void floatTestConstant(void) { + // Test that constants added to floats must be expressible as floating point + // numbers. + v4f32 v4f32_a = {0.4f, 0.4f, 0.4f, 0.4f}; + v4f32_a = v4f32_a + 1; + v4f32_a = v4f32_a + 0xFFFFFF; + v4f32_a = v4f32_a + (-1567563LL); // expected-warning {{'long long' is incompatible with C++98}} + v4f32_a = v4f32_a + (16777208); + v4f32_a = v4f32_a + (16777219); // expected-error {{cannot convert between scalar type 'int' and vector type 'v4f32' (vector of 4 'float' values) as implicit conversion would cause truncation}} +} + +void floatTestConstantComparison(void); +void doubleTestConstantComparison(void); + +void floatTestConstantComparison(void) { + v4f32 v4f32_a = {0.4f, 0.4f, 0.4f, 0.4f}; + v4i32 v4i32_r; + v4i32_r = v4f32_a > 0.4f; + v4i32_r = v4f32_a >= 0.4f; + v4i32_r = v4f32_a < 0.4f; + v4i32_r = v4f32_a <= 0.4f; + v4i32_r = v4f32_a == 0.4f; // expected-warning {{comparing floating point with == or != is unsafe}} + v4i32_r = v4f32_a != 0.4f; // expected-warning {{comparing floating point with == or != is unsafe}} +} + +void doubleTestConstantComparison(void) { + v2f64 v2f64_a = {0.4, 0.4}; + v2i64 v2i64_r; + v2i64_r = v2f64_a > 0.4; + v2i64_r = v2f64_a >= 0.4; + v2i64_r = v2f64_a < 0.4; + v2i64_r = v2f64_a <= 0.4; + v2i64_r = v2f64_a == 0.4; // expected-warning {{comparing floating point with == or != is unsafe}} + v2i64_r = v2f64_a != 0.4; // expected-warning {{comparing floating point with == or != is unsafe}} +} + +void floatTestUnsignedType(unsigned char a, unsigned short b, unsigned int c, + unsigned long long d) { // expected-warning {{'long long' is incompatible with C++98}} + v4f32 v4f32_a = {0.4f, 0.4f, 0.4f, 0.4f}; + v4f64 v4f64_b = {0.4, 0.4, 0.4, 0.4}; + + v4f32_a = v4f32_a + a; + v4f32_a = v4f32_a + b; + v4f32_a = v4f32_a + c; // expected-error {{cannot convert between scalar type 'unsigned int' and vector type 'v4f32' (vector of 4 'float' values) as implicit conversion would cause truncation}} + v4f32_a = v4f32_a + d; // expected-error {{cannot convert between scalar type 'unsigned long long' and vector type 'v4f32' (vector of 4 'float' values) as implicit conversion would cause truncation}} + + v4f64_b = v4f64_b + a; + v4f64_b = v4f64_b + b; + v4f64_b = v4f64_b + c; + v4f64_b = v4f64_b + d; // expected-error {{cannot convert between scalar type 'unsigned long long' and vector type 'v4f64' (vector of 4 'double' values) as implicit conversion would cause truncation}} +} + +void floatTestSignedType(char a, short b, int c, long long d) { // expected-warning {{'long long' is incompatible with C++98}} + v4f32 v4f32_a = {0.4f, 0.4f, 0.4f, 0.4f}; + v4f64 v4f64_b = {0.4, 0.4, 0.4, 0.4}; + + v4f32_a = v4f32_a + a; + v4f32_a = v4f32_a + b; + v4f32_a = v4f32_a + c; // expected-error {{cannot convert between scalar type 'int' and vector type 'v4f32' (vector of 4 'float' values) as implicit conversion would cause truncation}} + v4f32_a = v4f32_a + d; // expected-error {{cannot convert between scalar type 'long long' and vector type 'v4f32' (vector of 4 'float' values) as implicit conversion would cause truncation}} + + v4f64_b = v4f64_b + a; + v4f64_b = v4f64_b + b; + v4f64_b = v4f64_b + c; + v4f64_b = v4f64_b + d; // expected-error {{cannot convert between scalar type 'long long' and vector type 'v4f64' (vector of 4 'double' values) as implicit conversion would cause truncation}} +} + +void intTestType(char a, short b, int c, long long d) { // expected-warning {{'long long' is incompatible with C++98}} + v2i64 v2i64_a = {1, 2}; + v2i32 v2i32_a = {1, 2}; + v2i16 v2i16_a = {1, 2}; + v2i8 v2i8_a = {1, 2}; + + v2i64_a = v2i64_a + d; + v2i64_a = v2i64_a + c; + v2i64_a = v2i64_a + b; + v2i64_a = v2i64_a + a; + + v2i32_a = v2i32_a + d; // expected-warning {{implicit conversion loses integer precision: 'long long' to 'v2i32' (vector of 2 'int' values)}} + v2i32_a = v2i32_a + c; + v2i32_a = v2i32_a + b; + v2i32_a = v2i32_a + a; + + v2i16_a = v2i16_a + d; // expected-error {{cannot convert between scalar type 'long long' and vector type 'v2i16' (vector of 2 'short' values) as implicit conversion would cause truncation}} + v2i16_a = v2i16_a + c; // expected-warning {{implicit conversion loses integer precision: 'int' to 'v2i16' (vector of 2 'short' values)}} + v2i16_a = v2i16_a + b; + v2i16_a = v2i16_a + a; + + v2i8_a = v2i8_a + d; // expected-error {{cannot convert between scalar type 'long long' and vector type 'v2i8' (vector of 2 'char' values) as implicit conversion would cause truncation}} + v2i8_a = v2i8_a + c; // expected-error {{cannot convert between scalar type 'int' and vector type 'v2i8' (vector of 2 'char' values) as implicit conversion would cause truncation}} + v2i8_a = v2i8_a + b; // expected-warning {{implicit conversion loses integer precision: 'short' to 'v2i8' (vector of 2 'char' values)}} + v2i8_a = v2i8_a + a; +} + +void intTestTypeUnsigned(unsigned char a, unsigned short b, unsigned int c, + unsigned long long d) { // expected-warning {{'long long' is incompatible with C++98}} + v2i64 v2i64_a = {1, 2}; + v2i32 v2i32_a = {1, 2}; + v2i16 v2i16_a = {1, 2}; + v2i8 v2i8_a = {1, 2}; + + v2i64_a = v2i64_a + d; // expected-error {{cannot convert between scalar type 'unsigned long long' and vector type 'v2i64' (vector of 2 'long long' values) as implicit conversion would cause truncation}} + + v2i64_a = v2i64_a + c; + v2i64_a = v2i64_a + b; + v2i64_a = v2i64_a + a; + + v2i32_a = v2i32_a + d; // expected-warning {{implicit conversion loses integer precision: 'unsigned long long' to 'v2i32' (vector of 2 'int' values)}} + v2i32_a = v2i32_a + c; // expected-error {{cannot convert between scalar type 'unsigned int' and vector type 'v2i32' (vector of 2 'int' values) as implicit conversion would cause truncation}} + v2i32_a = v2i32_a + b; + v2i32_a = v2i32_a + a; + + v2i16_a = v2i16_a + d; // expected-error {{cannot convert between scalar type 'unsigned long long' and vector type 'v2i16' (vector of 2 'short' values) as implicit conversion would cause truncation}} + v2i16_a = v2i16_a + c; // expected-warning {{implicit conversion loses integer precision: 'unsigned int' to 'v2i16' (vector of 2 'short' values)}} + v2i16_a = v2i16_a + b; // expected-error {{cannot convert between scalar type 'unsigned short' and vector type 'v2i16' (vector of 2 'short' values) as implicit conversion would cause truncation}} + v2i16_a = v2i16_a + a; + + v2i8_a = v2i8_a + d; // expected-error {{cannot convert between scalar type 'unsigned long long' and vector type 'v2i8' (vector of 2 'char' values) as implicit conversion would cause truncation}} + v2i8_a = v2i8_a + c; // expected-error {{cannot convert between scalar type 'unsigned int' and vector type 'v2i8' (vector of 2 'char' values) as implicit conversion would cause truncation}} + v2i8_a = v2i8_a + b; // expected-warning {{implicit conversion loses integer precision: 'unsigned short' to 'v2i8' (vector of 2 'char' values)}} + v2i8_a = v2i8_a + a; // expected-error {{cannot convert between scalar type 'unsigned char' and vector type 'v2i8' (vector of 2 'char' values) as implicit conversion would cause truncation}} +} + +void uintTestType(char a, short b, int c, long long d) { // expected-warning {{'long long' is incompatible with C++98}} + v2u64 v2u64_a = {1, 2}; + v2u32 v2u32_a = {1, 2}; + v2u16 v2u16_a = {1, 2}; + v2u8 v2u8_a = {1, 2}; + + v2u64_a = v2u64_a + d; // expected-warning {{implicit conversion changes signedness: 'long long' to 'v2u64' (vector of 2 'unsigned long long' values)}} + v2u64_a = v2u64_a + c; // expected-warning {{implicit conversion changes signedness: 'int' to 'v2u64' (vector of 2 'unsigned long long' values)}} + v2u64_a = v2u64_a + b; // expected-warning {{implicit conversion changes signedness: 'short' to 'v2u64' (vector of 2 'unsigned long long' values)}} + v2u64_a = v2u64_a + a; // expected-warning {{implicit conversion changes signedness: 'char' to 'v2u64' (vector of 2 'unsigned long long' values)}} + + v2u32_a = v2u32_a + d; // expected-warning {{implicit conversion loses integer precision: 'long long' to 'v2u32' (vector of 2 'unsigned int' values)}} + v2u32_a = v2u32_a + c; // expected-warning {{implicit conversion changes signedness: 'int' to 'v2u32' (vector of 2 'unsigned int' values)}} + v2u32_a = v2u32_a + b; // expected-warning {{implicit conversion changes signedness: 'short' to 'v2u32' (vector of 2 'unsigned int' values)}} + v2u32_a = v2u32_a + a; // expected-warning {{implicit conversion changes signedness: 'char' to 'v2u32' (vector of 2 'unsigned int' values)}} + + v2u16_a = v2u16_a + d; // expected-error {{cannot convert between scalar type 'long long' and vector type 'v2u16' (vector of 2 'unsigned short' values) as implicit conversion would cause truncation}} + v2u16_a = v2u16_a + c; // expected-warning {{implicit conversion loses integer precision: 'int' to 'v2u16' (vector of 2 'unsigned short' values)}} + v2u16_a = v2u16_a + b; // expected-warning {{implicit conversion changes signedness: 'short' to 'v2u16' (vector of 2 'unsigned short' values)}} + v2u16_a = v2u16_a + a; // expected-warning {{implicit conversion changes signedness: 'char' to 'v2u16' (vector of 2 'unsigned short' values)}} + + v2u8_a = v2u8_a + d; // expected-error {{cannot convert between scalar type 'long long' and vector type 'v2u8' (vector of 2 'unsigned char' values) as implicit conversion would cause truncation}} + v2u8_a = v2u8_a + c; // expected-error {{cannot convert between scalar type 'int' and vector type 'v2u8' (vector of 2 'unsigned char' values) as implicit conversion would cause truncation}} + v2u8_a = v2u8_a + b; // expected-warning {{implicit conversion loses integer precision: 'short' to 'v2u8' (vector of 2 'unsigned char' values)}} + v2u8_a = v2u8_a + a; // expected-warning {{implicit conversion changes signedness: 'char' to 'v2u8' (vector of 2 'unsigned char' values)}} +} + +void uintTestTypeUnsigned(unsigned char a, unsigned short b, unsigned int c, + unsigned long long d) { // expected-warning {{'long long' is incompatible with C++98}} + v2u64 v2u64_a = {1, 2}; + v2u32 v2u32_a = {1, 2}; + v2u16 v2u16_a = {1, 2}; + v2u8 v2u8_a = {1, 2}; + + v2u64_a = v2u64_a + d; + v2u64_a = v2u64_a + c; + v2u64_a = v2u64_a + b; + v2u64_a = v2u64_a + a; + + v2u32_a = v2u32_a + d; // expected-warning {{implicit conversion loses integer precision: 'unsigned long long' to 'v2u32' (vector of 2 'unsigned int' values)}} + v2u32_a = v2u32_a + c; + v2u32_a = v2u32_a + b; + v2u32_a = v2u32_a + a; + + v2u16_a = v2u16_a + d; // expected-error {{cannot convert between scalar type 'unsigned long long' and vector type 'v2u16' (vector of 2 'unsigned short' values) as implicit conversion would cause truncation}} + v2u16_a = v2u16_a + c; // expected-warning {{implicit conversion loses integer precision: 'unsigned int' to 'v2u16' (vector of 2 'unsigned short' values)}} + v2u16_a = v2u16_a + b; + v2u16_a = v2u16_a + a; + + v2u8_a = v2u8_a + d; // expected-error {{cannot convert between scalar type 'unsigned long long' and vector type 'v2u8' (vector of 2 'unsigned char' values) as implicit conversion would cause truncation}} + v2u8_a = v2u8_a + c; // expected-error {{cannot convert between scalar type 'unsigned int' and vector type 'v2u8' (vector of 2 'unsigned char' values) as implicit conversion would cause truncation}} + v2u8_a = v2u8_a + b; // expected-warning {{implicit conversion loses integer precision: 'unsigned short' to 'v2u8' (vector of 2 'unsigned char' values)}} + v2u8_a = v2u8_a + a; +} + +void uintTestConstant(v2u64 v2u64_a, v2u32 v2u32_a, v2u16 v2u16_a, + v2u8 v2u8_a) { + v2u64_a = v2u64_a + 0xFFFFFFFFFFFFFFFF; + v2u32_a = v2u32_a + 0xFFFFFFFF; + v2u16_a = v2u16_a + 0xFFFF; + v2u8_a = v2u8_a + 0xFF; + + v2u32_a = v2u32_a + 0x1FFFFFFFF; // expected-warning {{implicit conversion from 'long' to 'v2u32' (vector of 2 'unsigned int' values) changes value from 8589934591 to 4294967295}} + v2u16_a = v2u16_a + 0x1FFFF; // expected-warning {{implicit conversion from 'int' to 'v2u16' (vector of 2 'unsigned short' values) changes value from 131071 to 65535}} + v2u8_a = v2u8_a + 0x1FF; // expected-error {{cannot convert between scalar type 'int' and vector type 'v2u8' (vector of 2 'unsigned char' values) as implicit conversion would cause truncation}} +} + +void intTestConstant(v2i64 v2i64_a, v2i32 v2i32_a, v2i16 v2i16_a, v2i8 v2i8_a) { + // Legal upper bounds. + v2i64_a = v2i64_a + static_cast(0x7FFFFFFFFFFFFFFF); // expected-warning {{'long long' is incompatible with C++98}} + v2i32_a = v2i32_a + static_cast(0x7FFFFFFF); + v2i16_a = v2i16_a + static_cast(0x7FFF); + v2i8_a = v2i8_a + static_cast(0x7F); + + // Legal lower bounds. + v2i64_a = v2i64_a + (-9223372036854775807); + v2i32_a = v2i32_a + (-2147483648); + v2i16_a = v2i16_a + (-32768); + v2i8_a = v2i8_a + (-128); + + // One increment/decrement more than the type can hold + v2i32_a = v2i32_a + 2147483648; // expected-warning {{implicit conversion from 'long' to 'v2i32' (vector of 2 'int' values) changes value from 2147483648 to -2147483648}} + v2i16_a = v2i16_a + 32768; // expected-warning {{implicit conversion from 'int' to 'v2i16' (vector of 2 'short' values) changes value from 32768 to -32768}} + v2i8_a = v2i8_a + 128; // expected-warning {{implicit conversion from 'int' to 'v2i8' (vector of 2 'char' values) changes value from 128 to -128}} + + v2i32_a = v2i32_a + (-2147483649); // expected-warning {{implicit conversion from 'long' to 'v2i32' (vector of 2 'int' values) changes value from -2147483649 to 2147483647}} + v2i16_a = v2i16_a + (-32769); // expected-warning {{implicit conversion from 'int' to 'v2i16' (vector of 2 'short' values) changes value from -32769 to 32767}} + v2i8_a = v2i8_a + (-129); // expected-error {{cannot convert between scalar type 'int' and vector type 'v2i8' (vector of 2 'char' values) as implicit conversion would cause truncation}} +} diff --git a/test/Sema/vector-ops.c b/test/Sema/vector-ops.c index 9cdd9d2f1748..575f38b972f5 100644 --- a/test/Sema/vector-ops.c +++ b/test/Sema/vector-ops.c @@ -13,11 +13,11 @@ void test1(v2u v2ua, v2s v2sa, v2f v2fa) { (void)(~v2fa); // expected-error{{invalid argument type 'v2f' (vector of 2 'float' values) to unary}} // Comparison operators - v2ua = (v2ua==v2sa); // expected-warning{{incompatible vector types assigning to 'v2u' (vector of 2 'unsigned int' values) from '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values)}} + v2ua = (v2ua==v2sa); // expected-warning{{incompatible vector types assigning to 'v2u' (vector of 2 'unsigned int' values) from '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values}} v2sa = (v2ua==v2sa); // Arrays - int array1[v2ua]; // expected-error{{size of array has non-integer type 'v2u' (vector of 2 'unsigned int' values)}} + int array1[v2ua]; // expected-error{{size of array has non-integer type 'v2u' (vector of 2 'unsigned int' values}} int array2[17]; // FIXME: error message below needs type! (void)(array2[v2ua]); // expected-error{{array subscript is not an integer}} @@ -28,108 +28,108 @@ void test1(v2u v2ua, v2s v2sa, v2f v2fa) { } void testLogicalVecVec(v2u v2ua, v2s v2sa, v2f v2fa) { - // Logical operators - v2ua = v2ua && v2ua; // expected-warning {{incompatible vector types assigning to 'v2u' (vector of 2 'unsigned int' values) from '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values)}} - v2ua = v2ua || v2ua; // expected-warning {{incompatible vector types assigning to 'v2u' (vector of 2 'unsigned int' values) from '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values)}} + v2ua = v2ua && v2ua; // expected-error {{logical expression with vector types 'v2u' (vector of 2 'unsigned int' values) and 'v2u'}} + v2ua = v2ua || v2ua; // expected-error {{logical expression with vector types 'v2u' (vector of 2 'unsigned int' values) and 'v2u'}} - v2ua = v2sa && v2ua; // expected-warning {{incompatible vector types assigning to 'v2u' (vector of 2 'unsigned int' values) from '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values)}} - v2ua = v2sa || v2ua; // expected-warning {{incompatible vector types assigning to 'v2u' (vector of 2 'unsigned int' values) from '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values)}} + v2ua = v2sa && v2ua; // expected-error {{logical expression with vector types 'v2s' (vector of 2 'int' values) and 'v2u' (vector of 2 'unsigned int' values)}} + v2ua = v2sa || v2ua; // expected-error {{logical expression with vector types 'v2s' (vector of 2 'int' values) and 'v2u' (vector of 2 'unsigned int' values)}} - v2ua = v2ua && v2fa; // expected-warning {{incompatible vector types assigning to 'v2u' (vector of 2 'unsigned int' values) from '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values)}} - v2ua = v2ua || v2fa; // expected-warning {{incompatible vector types assigning to 'v2u' (vector of 2 'unsigned int' values) from '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values)}} + v2ua = v2ua && v2fa; // expected-error {{logical expression with vector types 'v2u' (vector of 2 'unsigned int' values) and 'v2f' (vector of 2 'float' values)}} + v2ua = v2ua || v2fa; // expected-error {{logical expression with vector types 'v2u' (vector of 2 'unsigned int' values) and 'v2f' (vector of 2 'float' values)}} - v2ua = v2sa && v2fa; // expected-warning {{incompatible vector types assigning to 'v2u' (vector of 2 'unsigned int' values) from '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values)}} - v2ua = v2sa || v2fa; // expected-warning {{incompatible vector types assigning to 'v2u' (vector of 2 'unsigned int' values) from '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values)}} + v2ua = v2sa && v2fa; // expected-error {{logical expression with vector types 'v2s' (vector of 2 'int' values) and 'v2f' (vector of 2 'float' values)}} + v2ua = v2sa || v2fa; // expected-error {{logical expression with vector types 'v2s' (vector of 2 'int' values) and 'v2f' (vector of 2 'float' values)}} - v2sa = v2sa && v2sa; - v2sa = v2sa || v2sa; + v2sa = v2sa && v2sa; // expected-error {{logical expression with vector types 'v2s' (vector of 2 'int' values) and 'v2s'}} + v2sa = v2sa || v2sa; // expected-error {{logical expression with vector types 'v2s' (vector of 2 'int' values) and 'v2s'}} - v2sa = v2ua && v2ua; - v2sa = v2ua || v2ua; + v2sa = v2ua && v2ua; // expected-error {{logical expression with vector types 'v2u' (vector of 2 'unsigned int' values) and 'v2u'}} + v2sa = v2ua || v2ua; // expected-error {{logical expression with vector types 'v2u' (vector of 2 'unsigned int' values) and 'v2u'}} - v2sa = v2sa && v2ua; - v2sa = v2sa || v2ua; + v2sa = v2sa && v2ua; // expected-error {{logical expression with vector types 'v2s' (vector of 2 'int' values) and 'v2u' (vector of 2 'unsigned int' values)}} + v2sa = v2sa || v2ua; // expected-error {{logical expression with vector types 'v2s' (vector of 2 'int' values) and 'v2u' (vector of 2 'unsigned int' values)}} - v2sa = v2sa && v2fa; - v2sa = v2sa || v2fa; + v2sa = v2sa && v2fa; // expected-error {{logical expression with vector types 'v2s' (vector of 2 'int' values) and 'v2f' (vector of 2 'float' values)}} + v2sa = v2sa || v2fa; // expected-error {{logical expression with vector types 'v2s' (vector of 2 'int' values) and 'v2f' (vector of 2 'float' values)}} - v2sa = v2ua && v2fa; - v2sa = v2ua || v2fa; + v2sa = v2ua && v2fa; // expected-error {{logical expression with vector types 'v2u' (vector of 2 'unsigned int' values) and 'v2f' (vector of 2 'float' values)}} + v2sa = v2ua || v2fa; // expected-error {{logical expression with vector types 'v2u' (vector of 2 'unsigned int' values) and 'v2f' (vector of 2 'float' values)}} - v2fa = v2fa && v2fa; // expected-warning {{incompatible vector types assigning to 'v2f' (vector of 2 'float' values) from '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values)}} - v2fa = v2fa || v2fa; // expected-warning {{incompatible vector types assigning to 'v2f' (vector of 2 'float' values) from '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values)}} + v2fa = v2fa && v2fa; // expected-error {{logical expression with vector types 'v2f' (vector of 2 'float' values) and 'v2f'}} + v2fa = v2fa || v2fa; // expected-error {{logical expression with vector types 'v2f' (vector of 2 'float' values) and 'v2f'}} - v2fa = v2sa && v2fa; // expected-warning {{incompatible vector types assigning to 'v2f' (vector of 2 'float' values) from '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values)}} - v2fa = v2sa || v2fa; // expected-warning {{incompatible vector types assigning to 'v2f' (vector of 2 'float' values) from '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values)}} + v2fa = v2sa && v2fa; // expected-error {{logical expression with vector types 'v2s' (vector of 2 'int' values) and 'v2f' (vector of 2 'float' values)}} + v2fa = v2sa || v2fa; // expected-error {{logical expression with vector types 'v2s' (vector of 2 'int' values) and 'v2f' (vector of 2 'float' values)}} - v2fa = v2ua && v2fa; // expected-warning {{incompatible vector types assigning to 'v2f' (vector of 2 'float' values) from '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values)}} - v2fa = v2ua || v2fa; // expected-warning {{incompatible vector types assigning to 'v2f' (vector of 2 'float' values) from '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values)}} + v2fa = v2ua && v2fa; // expected-error {{logical expression with vector types 'v2u' (vector of 2 'unsigned int' values) and 'v2f' (vector of 2 'float' values)}} + v2fa = v2ua || v2fa; // expected-error {{logical expression with vector types 'v2u' (vector of 2 'unsigned int' values) and 'v2f' (vector of 2 'float' values)}} - v2fa = v2ua && v2ua; // expected-warning {{incompatible vector types assigning to 'v2f' (vector of 2 'float' values) from '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values)}} - v2fa = v2ua || v2ua; // expected-warning {{incompatible vector types assigning to 'v2f' (vector of 2 'float' values) from '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values)}} + v2fa = v2ua && v2ua; // expected-error {{logical expression with vector types 'v2u' (vector of 2 'unsigned int' values) and 'v2u'}} + v2fa = v2ua || v2ua; // expected-error {{logical expression with vector types 'v2u' (vector of 2 'unsigned int' values) and 'v2u'}} - v2fa = v2sa && v2sa; // expected-warning {{incompatible vector types assigning to 'v2f' (vector of 2 'float' values) from '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values)}} - v2fa = v2sa || v2sa; // expected-warning {{incompatible vector types assigning to 'v2f' (vector of 2 'float' values) from '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values)}} + v2fa = v2sa && v2sa; // expected-error {{logical expression with vector types 'v2s' (vector of 2 'int' values) and 'v2s'}} + v2fa = v2sa || v2sa; // expected-error {{logical expression with vector types 'v2s' (vector of 2 'int' values) and 'v2s'}} - v2fa = v2sa && v2ua; // expected-warning {{incompatible vector types assigning to 'v2f' (vector of 2 'float' values) from '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values)}} - v2fa = v2sa || v2ua; // expected-warning {{incompatible vector types assigning to 'v2f' (vector of 2 'float' values) from '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values)}} + v2fa = v2sa && v2ua; // expected-error {{logical expression with vector types 'v2s' (vector of 2 'int' values) and 'v2u' (vector of 2 'unsigned int' values)}} + v2fa = v2sa || v2ua; // expected-error {{logical expression with vector types 'v2s' (vector of 2 'int' values) and 'v2u' (vector of 2 'unsigned int' values)}} } void testLogicalVecScalar(v2u v2ua, v2s v2sa, v2f v2fa) { - unsigned u1; - v2ua = v2ua && u1; // expected-error {{cannot convert between vector values of different size ('v2u' (vector of 2 'unsigned int' values) and 'unsigned int')}} expected-error {{invalid operands to binary expression ('v2u' (vector of 2 'unsigned int' values) and 'unsigned int')}} - v2ua = v2ua || u1; // expected-error {{cannot convert between vector values of different size ('v2u' (vector of 2 'unsigned int' values) and 'unsigned int')}} expected-error {{invalid operands to binary expression ('v2u' (vector of 2 'unsigned int' values) and 'unsigned int')}} + v2ua = v2ua && u1; // expected-error {{logical expression with vector type 'v2u' (vector of 2 'unsigned int' values) and non-vector type 'unsigned int' is only supported in C++}} + v2ua = v2ua || u1; // expected-error {{logical expression with vector type 'v2u' (vector of 2 'unsigned int' values) and non-vector type 'unsigned int' is only supported in C++}} - v2sa = v2sa && u1; // expected-error {{cannot convert between vector values of different size ('v2s' (vector of 2 'int' values) and 'unsigned int')}} expected-error {{invalid operands to binary expression ('v2s' (vector of 2 'int' values) and 'unsigned int')}} - v2sa = v2sa || u1; // expected-error {{cannot convert between vector values of different size ('v2s' (vector of 2 'int' values) and 'unsigned int')}} expected-error {{invalid operands to binary expression ('v2s' (vector of 2 'int' values) and 'unsigned int')}} + v2sa = v2sa && u1; // expected-error {{cannot convert between scalar type 'unsigned int' and vector type 'v2s' (vector of 2 'int' values) as implicit conversion would cause truncation}} expected-error {{invalid operands to binary expression ('v2s' (vector of 2 'int' values) and 'unsigned int')}} + v2sa = v2sa || u1; // expected-error {{cannot convert between scalar type 'unsigned int' and vector type 'v2s' (vector of 2 'int' values) as implicit conversion would cause truncation}} expected-error {{invalid operands to binary expression ('v2s' (vector of 2 'int' values) and 'unsigned int')}} - v2ua = v2sa && u1; // expected-error {{cannot convert between vector values of different size ('v2s' (vector of 2 'int' values) and 'unsigned int')}} expected-error {{invalid operands to binary expression ('v2s' (vector of 2 'int' values) and 'unsigned int')}} - v2ua = v2sa || u1; // expected-error {{cannot convert between vector values of different size ('v2s' (vector of 2 'int' values) and 'unsigned int')}} expected-error {{invalid operands to binary expression ('v2s' (vector of 2 'int' values) and 'unsigned int')}} - v2sa = v2ua && u1; // expected-error {{cannot convert between vector values of different size ('v2u' (vector of 2 'unsigned int' values) and 'unsigned int')}} expected-error {{invalid operands to binary expression ('v2u' (vector of 2 'unsigned int' values) and 'unsigned int')}} - v2sa = v2ua || u1; // expected-error {{cannot convert between vector values of different size ('v2u' (vector of 2 'unsigned int' values) and 'unsigned int')}} expected-error {{invalid operands to binary expression ('v2u' (vector of 2 'unsigned int' values) and 'unsigned int')}} + v2ua = v2sa && u1; // expected-error {{cannot convert between scalar type 'unsigned int' and vector type 'v2s' (vector of 2 'int' values) as implicit conversion would cause truncation}} expected-error {{invalid operands to binary expression ('v2s' (vector of 2 'int' values) and 'unsigned int')}} + v2ua = v2sa || u1; // expected-error {{cannot convert between scalar type 'unsigned int' and vector type 'v2s' (vector of 2 'int' values) as implicit conversion would cause truncation}} expected-error {{invalid operands to binary expression ('v2s' (vector of 2 'int' values) and 'unsigned int')}} + v2sa = v2ua && u1; // expected-error {{logical expression with vector type 'v2u' (vector of 2 'unsigned int' values) and non-vector type 'unsigned int' is only supported in C++}} + v2sa = v2ua || u1; // expected-error {{logical expression with vector type 'v2u' (vector of 2 'unsigned int' values) and non-vector type 'unsigned int' is only supported in C++}} - v2ua = v2fa && u1; // expected-error {{cannot convert between vector values of different size ('v2f' (vector of 2 'float' values) and 'unsigned int')}} expected-error {{invalid operands to binary expression ('v2f' (vector of 2 'float' values) and 'unsigned int')}} - v2ua = v2fa || u1; // expected-error {{cannot convert between vector values of different size ('v2f' (vector of 2 'float' values) and 'unsigned int')}} expected-error {{invalid operands to binary expression ('v2f' (vector of 2 'float' values) and 'unsigned int')}} + v2ua = v2fa && u1; // expected-error {{cannot convert between scalar type 'unsigned int' and vector type 'v2f' (vector of 2 'float' values) as implicit conversion would cause truncation}} expected-error {{invalid operands to binary expression ('v2f' (vector of 2 'float' values) and 'unsigned int')}} + v2ua = v2fa || u1; // expected-error {{cannot convert between scalar type 'unsigned int' and vector type 'v2f' (vector of 2 'float' values) as implicit conversion would cause truncation}} expected-error {{invalid operands to binary expression ('v2f' (vector of 2 'float' values) and 'unsigned int')}} - v2sa = v2fa && u1; // expected-error {{cannot convert between vector values of different size ('v2f' (vector of 2 'float' values) and 'unsigned int')}} expected-error {{invalid operands to binary expression ('v2f' (vector of 2 'float' values) and 'unsigned int')}} - v2sa = v2fa || u1; // expected-error {{cannot convert between vector values of different size ('v2f' (vector of 2 'float' values) and 'unsigned int')}} expected-error {{invalid operands to binary expression ('v2f' (vector of 2 'float' values) and 'unsigned int')}} + v2sa = v2fa && u1; // expected-error {{cannot convert between scalar type 'unsigned int' and vector type 'v2f' (vector of 2 'float' values) as implicit conversion would cause truncation}} expected-error {{invalid operands to binary expression ('v2f' (vector of 2 'float' values) and 'unsigned int')}} + v2sa = v2fa || u1; // expected-error {{cannot convert between scalar type 'unsigned int' and vector type 'v2f' (vector of 2 'float' values) as implicit conversion would cause truncation}} expected-error {{invalid operands to binary expression ('v2f' (vector of 2 'float' values) and 'unsigned int')}} int s1; - v2ua = v2ua && s1; // expected-error {{cannot convert between vector values of different size ('v2u' (vector of 2 'unsigned int' values) and 'int')}} expected-error {{invalid operands to binary expression ('v2u' (vector of 2 'unsigned int' values) and 'int')}} - v2ua = v2ua || s1; // expected-error {{cannot convert between vector values of different size ('v2u' (vector of 2 'unsigned int' values) and 'int')}} expected-error {{invalid operands to binary expression ('v2u' (vector of 2 'unsigned int' values) and 'int')}} + v2ua = v2ua && s1; // expected-error {{logical expression with vector type 'v2u' (vector of 2 'unsigned int' values) and non-vector type 'int' is only supported in C++}} + v2ua = v2ua || s1; // expected-error {{logical expression with vector type 'v2u' (vector of 2 'unsigned int' values) and non-vector type 'int' is only supported in C++}} - v2sa = v2sa && s1; // expected-error {{cannot convert between vector values of different size ('v2s' (vector of 2 'int' values) and 'int')}} expected-error {{invalid operands to binary expression ('v2s' (vector of 2 'int' values) and 'int')}} - v2sa = v2sa || s1; // expected-error {{cannot convert between vector values of different size ('v2s' (vector of 2 'int' values) and 'int')}} expected-error {{invalid operands to binary expression ('v2s' (vector of 2 'int' values) and 'int')}} + v2sa = v2sa && s1; // expected-error {{logical expression with vector type 'v2s' (vector of 2 'int' values) and non-vector type 'int' is only supported in C++}} + v2sa = v2sa || s1; // expected-error {{logical expression with vector type 'v2s' (vector of 2 'int' values) and non-vector type 'int' is only supported in C++}} - v2ua = v2sa && s1; // expected-error {{cannot convert between vector values of different size ('v2s' (vector of 2 'int' values) and 'int')}} expected-error {{invalid operands to binary expression ('v2s' (vector of 2 'int' values) and 'int')}} - v2ua = v2sa || s1; // expected-error {{cannot convert between vector values of different size ('v2s' (vector of 2 'int' values) and 'int')}} expected-error {{invalid operands to binary expression ('v2s' (vector of 2 'int' values) and 'int')}} - v2sa = v2ua && s1; // expected-error {{cannot convert between vector values of different size ('v2u' (vector of 2 'unsigned int' values) and 'int')}} expected-error {{invalid operands to binary expression ('v2u' (vector of 2 'unsigned int' values) and 'int')}} - v2sa = v2ua || s1; // expected-error {{cannot convert between vector values of different size ('v2u' (vector of 2 'unsigned int' values) and 'int')}} expected-error {{invalid operands to binary expression ('v2u' (vector of 2 'unsigned int' values) and 'int')}} + v2ua = v2sa && s1; // expected-error {{logical expression with vector type 'v2s' (vector of 2 'int' values) and non-vector type 'int' is only supported in C++}} + v2ua = v2sa || s1; // expected-error {{logical expression with vector type 'v2s' (vector of 2 'int' values) and non-vector type 'int' is only supported in C++}} - v2ua = v2fa && s1; // expected-error {{cannot convert between vector values of different size ('v2f' (vector of 2 'float' values) and 'int')}} expected-error {{invalid operands to binary expression ('v2f' (vector of 2 'float' values) and 'int')}} - v2ua = v2fa || s1; // expected-error {{cannot convert between vector values of different size ('v2f' (vector of 2 'float' values) and 'int')}} expected-error {{invalid operands to binary expression ('v2f' (vector of 2 'float' values) and 'int')}} + v2sa = v2ua && s1; // expected-error {{logical expression with vector type 'v2u' (vector of 2 'unsigned int' values) and non-vector type 'int' is only supported in C++}} + v2sa = v2ua || s1; // expected-error {{logical expression with vector type 'v2u' (vector of 2 'unsigned int' values) and non-vector type 'int' is only supported in C++}} - v2sa = v2fa && s1; // expected-error {{cannot convert between vector values of different size ('v2f' (vector of 2 'float' values) and 'int')}} expected-error {{invalid operands to binary expression ('v2f' (vector of 2 'float' values) and 'int')}} - v2sa = v2fa || s1; // expected-error {{cannot convert between vector values of different size ('v2f' (vector of 2 'float' values) and 'int')}} expected-error {{invalid operands to binary expression ('v2f' (vector of 2 'float' values) and 'int')}} + v2ua = v2fa && s1; // expected-error {{cannot convert between scalar type 'int' and vector type 'v2f' (vector of 2 'float' values) as implicit conversion would cause truncation}} expected-error {{invalid operands to binary expression ('v2f' (vector of 2 'float' values) and 'int'}} + v2ua = v2fa || s1; // expected-error {{cannot convert between scalar type 'int' and vector type 'v2f' (vector of 2 'float' values) as implicit conversion would cause truncation}} expected-error {{invalid operands to binary expression ('v2f' (vector of 2 'float' values) and 'int'}} + + v2sa = v2fa && s1; // expected-error {{cannot convert between scalar type 'int' and vector type 'v2f' (vector of 2 'float' values) as implicit conversion would cause truncation}} expected-error {{invalid operands to binary expression ('v2f' (vector of 2 'float' values) and 'int'}} + v2sa = v2fa || s1; // expected-error {{cannot convert between scalar type 'int' and vector type 'v2f' (vector of 2 'float' values) as implicit conversion would cause truncation}} expected-error {{invalid operands to binary expression ('v2f' (vector of 2 'float' values) and 'int'}} float f1; - v2ua = v2ua && f1; // expected-error {{cannot convert between vector values of different size ('v2u' (vector of 2 'unsigned int' values) and 'float')}} expected-error {{invalid operands to binary expression ('v2u' (vector of 2 'unsigned int' values) and 'float')}} - v2ua = v2ua || f1; // expected-error {{cannot convert between vector values of different size ('v2u' (vector of 2 'unsigned int' values) and 'float')}} expected-error {{invalid operands to binary expression ('v2u' (vector of 2 'unsigned int' values) and 'float')}} + v2ua = v2ua && f1; // expected-error {{logical expression with vector type 'v2u' (vector of 2 'unsigned int' values) and non-vector type 'float' is only supported in C++}} + v2ua = v2ua || f1; // expected-error {{logical expression with vector type 'v2u' (vector of 2 'unsigned int' values) and non-vector type 'float' is only supported in C++}} - v2sa = v2sa && f1; // expected-error {{cannot convert between vector values of different size ('v2s' (vector of 2 'int' values) and 'float')}} expected-error {{invalid operands to binary expression ('v2s' (vector of 2 'int' values) and 'float')}} - v2sa = v2sa || f1; // expected-error {{cannot convert between vector values of different size ('v2s' (vector of 2 'int' values) and 'float')}} expected-error {{invalid operands to binary expression ('v2s' (vector of 2 'int' values) and 'float')}} + v2sa = v2sa && f1; // expected-error {{logical expression with vector type 'v2s' (vector of 2 'int' values) and non-vector type 'float' is only supported in C++}} + v2sa = v2sa || f1; // expected-error {{logical expression with vector type 'v2s' (vector of 2 'int' values) and non-vector type 'float' is only supported in C++}} - v2ua = v2sa && f1; // expected-error {{cannot convert between vector values of different size ('v2s' (vector of 2 'int' values) and 'float')}} expected-error {{invalid operands to binary expression ('v2s' (vector of 2 'int' values) and 'float')}} - v2ua = v2sa || f1; // expected-error {{cannot convert between vector values of different size ('v2s' (vector of 2 'int' values) and 'float')}} expected-error {{invalid operands to binary expression ('v2s' (vector of 2 'int' values) and 'float')}} - v2sa = v2ua && f1; // expected-error {{cannot convert between vector values of different size ('v2u' (vector of 2 'unsigned int' values) and 'float')}} expected-error {{invalid operands to binary expression ('v2u' (vector of 2 'unsigned int' values) and 'float')}} - v2sa = v2ua || f1; // expected-error {{cannot convert between vector values of different size ('v2u' (vector of 2 'unsigned int' values) and 'float')}} expected-error {{invalid operands to binary expression ('v2u' (vector of 2 'unsigned int' values) and 'float')}} + v2ua = v2sa && f1; // expected-error {{logical expression with vector type 'v2s' (vector of 2 'int' values) and non-vector type 'float' is only supported in C++}} + v2ua = v2sa || f1; // expected-error {{logical expression with vector type 'v2s' (vector of 2 'int' values) and non-vector type 'float' is only supported in C++}} - v2ua = v2fa && f1; // expected-error {{cannot convert between vector values of different size ('v2f' (vector of 2 'float' values) and 'float')}} expected-error {{invalid operands to binary expression ('v2f' (vector of 2 'float' values) and 'float')}} - v2ua = v2fa || f1; // expected-error {{cannot convert between vector values of different size ('v2f' (vector of 2 'float' values) and 'float')}} expected-error {{invalid operands to binary expression ('v2f' (vector of 2 'float' values) and 'float')}} + v2sa = v2ua && f1; // expected-error {{logical expression with vector type 'v2u' (vector of 2 'unsigned int' values) and non-vector type 'float' is only supported in C++}} + v2sa = v2ua || f1; // expected-error {{logical expression with vector type 'v2u' (vector of 2 'unsigned int' values) and non-vector type 'float' is only supported in C++}} - v2sa = v2fa && f1; // expected-error {{cannot convert between vector values of different size ('v2f' (vector of 2 'float' values) and 'float')}} expected-error {{invalid operands to binary expression ('v2f' (vector of 2 'float' values) and 'float')}} - v2sa = v2fa || f1; // expected-error {{cannot convert between vector values of different size ('v2f' (vector of 2 'float' values) and 'float')}} expected-error {{invalid operands to binary expression ('v2f' (vector of 2 'float' values) and 'float')}} + v2ua = v2fa && f1; // expected-error {{logical expression with vector type 'v2f' (vector of 2 'float' values) and non-vector type 'float' is only supported in C++}} + v2ua = v2fa || f1; // expected-error {{logical expression with vector type 'v2f' (vector of 2 'float' values) and non-vector type 'float' is only supported in C++}} + + v2sa = v2fa && f1; // expected-error {{logical expression with vector type 'v2f' (vector of 2 'float' values) and non-vector type 'float' is only supported in C++}} + v2sa = v2fa || f1; // expected-error {{logical expression with vector type 'v2f' (vector of 2 'float' values) and non-vector type 'float' is only supported in C++}} } diff --git a/test/Sema/zvector.c b/test/Sema/zvector.c index d1cf1aa01f4b..740163fcd9d5 100644 --- a/test/Sema/zvector.c +++ b/test/Sema/zvector.c @@ -326,14 +326,14 @@ void foo(void) bc = bc + sc2; // expected-error {{incompatible type}} bc = sc + bc2; // expected-error {{incompatible type}} - sc = sc + sc_scalar; // expected-error {{cannot convert}} - sc = sc + uc_scalar; // expected-error {{cannot convert}} - sc = sc_scalar + sc; // expected-error {{cannot convert}} - sc = uc_scalar + sc; // expected-error {{cannot convert}} - uc = uc + sc_scalar; // expected-error {{cannot convert}} - uc = uc + uc_scalar; // expected-error {{cannot convert}} - uc = sc_scalar + uc; // expected-error {{cannot convert}} - uc = uc_scalar + uc; // expected-error {{cannot convert}} + sc = sc + sc_scalar; + sc = sc + uc_scalar; // expected-error {{cannot convert between scalar type 'unsigned char' and vector type '__vector signed char' (vector of 16 'signed char' values) as implicit conversion would cause truncation}} + sc = sc_scalar + sc; + sc = uc_scalar + sc; // expected-error {{cannot convert between scalar type 'unsigned char' and vector type '__vector signed char' (vector of 16 'signed char' values) as implicit conversion would cause truncation}} + uc = uc + sc_scalar; // expected-error {{implicit conversion changes signedness: 'signed char' to '__vector unsigned char' (vector of 16 'unsigned char' values)}} + uc = uc + uc_scalar; + uc = sc_scalar + uc; // expected-error {{implicit conversion changes signedness: 'signed char' to '__vector unsigned char' (vector of 16 'unsigned char' values)}} + uc = uc_scalar + uc; ss = ss + ss2; us = us + us2; @@ -368,10 +368,10 @@ void foo(void) sc += sl2; // expected-error {{cannot convert}} sc += fd2; // expected-error {{cannot convert}} - sc += sc_scalar; // expected-error {{cannot convert}} - sc += uc_scalar; // expected-error {{cannot convert}} - uc += sc_scalar; // expected-error {{cannot convert}} - uc += uc_scalar; // expected-error {{cannot convert}} + sc += sc_scalar; + sc += uc_scalar; // expected-error {{cannot convert between scalar type 'unsigned char' and vector type '__vector signed char' (vector of 16 'signed char' values) as implicit conversion would cause truncation}} + uc += sc_scalar; // expected-error {{implicit conversion changes signedness: 'signed char' to '__vector unsigned char' (vector of 16 'unsigned char' values)}} + uc += uc_scalar; ss += ss2; us += us2; diff --git a/test/SemaCXX/constructor-initializer.cpp b/test/SemaCXX/constructor-initializer.cpp index c5de33cedb90..102ff1e80d03 100644 --- a/test/SemaCXX/constructor-initializer.cpp +++ b/test/SemaCXX/constructor-initializer.cpp @@ -302,3 +302,22 @@ namespace PR14073 { struct S2 { union { union { int n; }; char c; }; S2() : n(n) {} }; // expected-warning {{field 'n' is uninitialized when used here}} struct S3 { struct { int n; }; S3() : n(n) {} }; // expected-warning {{field 'n' is uninitialized when used here}} } + +namespace PR10758 { +struct A; +struct B { + B (A const &); // expected-note 2 {{candidate constructor not viable: no known conversion from 'const PR10758::B' to 'const PR10758::A &' for 1st argument}} + B (B &); // expected-note 2 {{candidate constructor not viable: 1st argument ('const PR10758::B') would lose const qualifier}} +}; +struct A { + A (B); // expected-note 2 {{passing argument to parameter here}} +}; + +B f(B const &b) { + return b; // expected-error {{no matching constructor for initialization of 'PR10758::B'}} +} + +A f2(const B &b) { + return b; // expected-error {{no matching constructor for initialization of 'PR10758::B'}} +} +} diff --git a/test/SemaCXX/cxx1y-generic-lambdas.cpp b/test/SemaCXX/cxx1y-generic-lambdas.cpp index 1993c6e1853d..9f3c77591a86 100644 --- a/test/SemaCXX/cxx1y-generic-lambdas.cpp +++ b/test/SemaCXX/cxx1y-generic-lambdas.cpp @@ -986,3 +986,10 @@ class Enclosing3 { ); }; } + +namespace PR32638 { + //https://bugs.llvm.org/show_bug.cgi?id=32638 + void test() { + [](auto x) noexcept(noexcept(x)) { } (0); + } +} \ No newline at end of file diff --git a/test/SemaCXX/cxx1y-variable-templates_top_level.cpp b/test/SemaCXX/cxx1y-variable-templates_top_level.cpp index b4963646838c..a78548b6f128 100644 --- a/test/SemaCXX/cxx1y-variable-templates_top_level.cpp +++ b/test/SemaCXX/cxx1y-variable-templates_top_level.cpp @@ -9,7 +9,7 @@ #endif template -T pi = T(3.1415926535897932385); // expected-note {{template is declared here}} +T pi = T(3.1415926535897932385); // expected-note 2{{declared here}} template CONST T cpi = T(3.1415926535897932385); // expected-note {{template is declared here}} @@ -58,10 +58,9 @@ namespace use_in_top_level_funcs { namespace shadow { void foo() { int ipi0 = pi; - int pi; + int pi; // expected-note {{found}} int a = pi; - int ipi = pi; // expected-error {{expected '(' for function-style cast or type construction}} \ - // expected-error {{expected expression}} + int ipi = pi; // expected-error {{'pi' does not name a template but is followed by template arguments; did you mean '::pi'?}} } } diff --git a/test/SemaCXX/enable_if.cpp b/test/SemaCXX/enable_if.cpp index 9a06d3866110..93014f50d508 100644 --- a/test/SemaCXX/enable_if.cpp +++ b/test/SemaCXX/enable_if.cpp @@ -499,3 +499,17 @@ void run() { } } } + +namespace TypeOfFn { + template + struct is_same; + + template struct is_same { + enum { value = 1 }; + }; + + void foo(int a) __attribute__((enable_if(a, ""))); + void foo(float a) __attribute__((enable_if(1, ""))); + + static_assert(is_same<__typeof__(foo)*, decltype(&foo)>::value, ""); +} diff --git a/test/SemaCXX/for-range-examples.cpp b/test/SemaCXX/for-range-examples.cpp index 08a9982c6378..d6b527ff8a50 100644 --- a/test/SemaCXX/for-range-examples.cpp +++ b/test/SemaCXX/for-range-examples.cpp @@ -241,3 +241,37 @@ namespace pr18587 { } } } + +namespace PR32933 { +// https://bugs.llvm.org/show_bug.cgi?id=32933 +void foo () +{ + int b = 1, a[b]; + a[0] = 0; + [&] { for (int c : a) 0; } (); +} + + +int foo(int b) { + int varr[b][(b+=8)]; + b = 15; + [&] { + int i = 0; + for (auto &c : varr) + { + c[0] = ++b; + } + [&] { + int i = 0; + for (auto &c : varr) { + int j = 0; + for(auto &c2 : c) { + ++j; + } + ++i; + } + }(); + }(); + return b; +} +} \ No newline at end of file diff --git a/test/SemaCXX/invalid-member-expr.cpp b/test/SemaCXX/invalid-member-expr.cpp index 172be6b8266d..fd50d328da67 100644 --- a/test/SemaCXX/invalid-member-expr.cpp +++ b/test/SemaCXX/invalid-member-expr.cpp @@ -53,9 +53,7 @@ namespace test3 { namespace rdar11293995 { struct Length { - explicit Length(PassRefPtr); // expected-error {{unknown type name}} \ - expected-error {{expected ')'}} \ - expected-note {{to match this '('}} + explicit Length(PassRefPtr); // expected-error {{no template named 'PassRefPtr}} expected-error {{undeclared identifier 'CalculationValue'}} }; struct LengthSize { diff --git a/test/SemaCXX/modules-ts.cppm b/test/SemaCXX/modules-ts.cppm index 16695f6463a8..d1d7aaa96e6c 100644 --- a/test/SemaCXX/modules-ts.cppm +++ b/test/SemaCXX/modules-ts.cppm @@ -17,7 +17,8 @@ static int m; // ok, internal linkage, so no redefinition error int n; #if TEST >= 2 // expected-error@-2 {{redefinition of '}} -// expected-note@-3 {{previous}} +// expected-note@-3 {{unguarded header; consider using #ifdef guards or #pragma once}} +// expected-note-re@modules-ts.cppm:1 {{'{{.*}}modules-ts.cppm' included multiple times, additional include site here}} #endif #if TEST == 0 diff --git a/test/SemaCXX/type-traits.cpp b/test/SemaCXX/type-traits.cpp index 9da59b93c503..919122576222 100644 --- a/test/SemaCXX/type-traits.cpp +++ b/test/SemaCXX/type-traits.cpp @@ -1256,7 +1256,7 @@ void is_trivially_copyable2() int t33[F(__is_trivially_copyable(ExtDefaulted))]; int t34[T(__is_trivially_copyable(const int))]; - int t35[F(__is_trivially_copyable(volatile int))]; + int t35[T(__is_trivially_copyable(volatile int))]; } struct CStruct { diff --git a/test/SemaCXX/typo-correction.cpp b/test/SemaCXX/typo-correction.cpp index c59ee618f929..2d78f06c5d33 100644 --- a/test/SemaCXX/typo-correction.cpp +++ b/test/SemaCXX/typo-correction.cpp @@ -524,13 +524,16 @@ namespace shadowed_template { template class Fizbin {}; // expected-note {{'::shadowed_template::Fizbin' declared here}} class Baz { int Fizbin(); - // TODO: Teach the parser to recover from the typo correction instead of - // continuing to treat the template name as an implicit-int declaration. - Fizbin qux; // expected-error {{unknown type name 'Fizbin'; did you mean '::shadowed_template::Fizbin'?}} \ - // expected-error {{expected member name or ';' after declaration specifiers}} + Fizbin qux; // expected-error {{no template named 'Fizbin'; did you mean '::shadowed_template::Fizbin'?}} }; } +namespace no_correct_template_id_to_non_template { + struct Frobnatz {}; // expected-note {{declared here}} + Frobnats fn; // expected-error {{unknown type name 'Frobnats'; did you mean 'Frobnatz'?}} + Frobnats fni; // expected-error-re {{no template named 'Frobnats'{{$}}}} +} + namespace PR18852 { void func() { struct foo { diff --git a/test/SemaCXX/vector-no-lax.cpp b/test/SemaCXX/vector-no-lax.cpp index a85f7f9db060..3cedcb1e8ce5 100644 --- a/test/SemaCXX/vector-no-lax.cpp +++ b/test/SemaCXX/vector-no-lax.cpp @@ -4,6 +4,6 @@ typedef int __attribute__((vector_size (16))) vSInt32; vSInt32 foo (vUInt32 a) { vSInt32 b = { 0, 0, 0, 0 }; - b += a; // expected-error{{cannot convert between vector values}} + b += a; // expected-error{{cannot convert between vector type 'vUInt32' (vector of 4 'unsigned int' values) and vector type 'vSInt32' (vector of 4 'int' values) as implicit conversion would cause truncation}} return b; } diff --git a/test/SemaCXX/warn-unused-filescoped.cpp b/test/SemaCXX/warn-unused-filescoped.cpp index 18defee7d04a..93c6bbd7edc9 100644 --- a/test/SemaCXX/warn-unused-filescoped.cpp +++ b/test/SemaCXX/warn-unused-filescoped.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -Wunused -Wunused-member-function -Wno-unused-local-typedefs -Wno-c++11-extensions -std=c++98 %s -// RUN: %clang_cc1 -fsyntax-only -verify -Wunused -Wunused-member-function -Wno-unused-local-typedefs -std=c++11 %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wunused -Wunused-template -Wunused-member-function -Wno-unused-local-typedefs -Wno-c++11-extensions -std=c++98 %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wunused -Wunused-template -Wunused-member-function -Wno-unused-local-typedefs -std=c++14 %s #ifdef HEADER @@ -65,7 +65,7 @@ namespace { template <> void TS::m() { } // expected-warning{{unused}} template - void tf() { } + void tf() { } // expected-warning{{unused}} template <> void tf() { } // expected-warning{{unused}} struct VS { @@ -200,6 +200,18 @@ void bar() { void func() __attribute__((used)); } static void func() {} } +namespace test9 { +template +static void completeRedeclChainForTemplateSpecialization() { } // expected-warning {{unused}} +} + +namespace test10 { +#if __cplusplus >= 201103L +template +constexpr T pi = T(3.14); // expected-warning {{unused}} +#endif +} + namespace pr19713 { #if __cplusplus >= 201103L // FIXME: We should warn on both of these. diff --git a/test/SemaObjC/method-bad-param.m b/test/SemaObjC/method-bad-param.m index ad67a34edb00..a7f0745ddbad 100644 --- a/test/SemaObjC/method-bad-param.m +++ b/test/SemaObjC/method-bad-param.m @@ -20,6 +20,12 @@ } @end +// Ensure that this function is properly marked as a failure. +void func_with_bad_call(bar* b, foo* f) { + [b cccccc:5]; // expected-warning {{instance method '-cccccc:' not found}} + // expected-note@-17 {{receiver is instance of class declared here}} +} + void somefunc(foo x) {} // expected-error {{interface type 'foo' cannot be passed by value; did you forget * in 'foo'}} foo somefunc2() {} // expected-error {{interface type 'foo' cannot be returned by value; did you forget * in 'foo'}} diff --git a/test/SemaObjC/unguarded-availability.m b/test/SemaObjC/unguarded-availability.m index ae921f4a27b3..071a21ea1b3f 100644 --- a/test/SemaObjC/unguarded-availability.m +++ b/test/SemaObjC/unguarded-availability.m @@ -8,7 +8,7 @@ int func_10_11() AVAILABLE_10_11; // expected-note 4 {{'func_10_11' has been explicitly marked partial here}} #ifdef OBJCPP -// expected-note@+2 2 {{marked partial here}} +// expected-note@+2 6 {{marked partial here}} #endif int func_10_12() AVAILABLE_10_12; // expected-note 6 {{'func_10_12' has been explicitly marked partial here}} @@ -48,7 +48,7 @@ void star_case() { } else func_10_11(); // expected-warning{{'func_10_11' is only available on macOS 10.11 or newer}} expected-note{{enclose 'func_10_11' in an @available check to silence this warning}} - if (@available(macos 10.11, *)) { + if (@available(macOS 10.11, *)) { if (@available(ios 8, *)) { func_10_11(); func_10_12(); // expected-warning{{'func_10_12' is only available on macOS 10.12 or newer}} expected-note{{enclose}} @@ -176,7 +176,7 @@ int instantiate_with_availability_attr() { } int instantiate_availability() { - if (@available(macos 10.12, *)) + if (@available(macOS 10.12, *)) with_availability_attr(); else with_availability_attr(); // expected-warning{{'with_availability_attr' is only available on macOS 10.11 or newer}} expected-warning{{'int_10_12' is only available on macOS 10.12 or newer}} expected-note 2 {{enclose}} @@ -188,4 +188,19 @@ auto topLevelLambda = [] () { func_10_12(); }; +void functionInFunction() { + func_10_12(); // expected-warning{{'func_10_12' is only available on macOS 10.12 or newer}} expected-note{{@available}} + struct DontWarnTwice { + void f() { + func_10_12(); // expected-warning{{'func_10_12' is only available on macOS 10.12 or newer}} expected-note{{@available}} + } + }; + void([] () { + func_10_12(); // expected-warning{{'func_10_12' is only available on macOS 10.12 or newer}} expected-note{{@available}} + }); + (void)(^ { + func_10_12(); // expected-warning{{'func_10_12' is only available on macOS 10.12 or newer}} expected-note{{@available}} + }); +} + #endif diff --git a/test/SemaObjCXX/interface-return-type.mm b/test/SemaObjCXX/interface-return-type.mm new file mode 100644 index 000000000000..9fff8610ae0d --- /dev/null +++ b/test/SemaObjCXX/interface-return-type.mm @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify + +@class NSObject; +template struct C { + static T f(); // expected-error {{interface type 'NSObject' cannot be returned by value; did you forget * in 'NSObject'?}} +}; +int g() { NSObject *x = C::f(); }//expected-error {{no member named 'f' in 'C'}} expected-note {{in instantiation of template class 'C' requested here}} diff --git a/test/SemaObjCXX/is-base-of.mm b/test/SemaObjCXX/is-base-of.mm new file mode 100644 index 000000000000..9cf16661b0c5 --- /dev/null +++ b/test/SemaObjCXX/is-base-of.mm @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +@interface NSObj +@end + +@interface NSChild : NSObj +@end + +static_assert(__is_base_of(NSObj, NSChild), ""); +static_assert(!__is_base_of(NSChild, NSObj), ""); + +static_assert(__is_base_of(NSObj, NSObj), ""); + +static_assert(!__is_base_of(NSObj *, NSChild *), ""); +static_assert(!__is_base_of(NSChild *, NSObj *), ""); + +static_assert(__is_base_of(const volatile NSObj, NSChild), ""); +static_assert(__is_base_of(NSObj, const volatile NSChild), ""); + +@class NSForward; // expected-note{{forward declaration of class}} + +static_assert(!__is_base_of(NSForward, NSObj), ""); +static_assert(!__is_base_of(NSObj, NSForward), ""); // expected-error{{incomplete type 'NSForward'}} + +static_assert(!__is_base_of(id, NSObj), ""); diff --git a/test/SemaOpenCL/array-init.cl b/test/SemaOpenCL/array-init.cl new file mode 100644 index 000000000000..d9691d86dd81 --- /dev/null +++ b/test/SemaOpenCL/array-init.cl @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL2.0 +// expected-no-diagnostics + +__kernel void k1(queue_t q1, queue_t q2) { + queue_t q[] = {q1, q2}; +} + +__kernel void k2(read_only pipe int p) { + reserve_id_t i1 = reserve_read_pipe(p, 1); + reserve_id_t i2 = reserve_read_pipe(p, 1); + reserve_id_t i[] = {i1, i2}; +} + +event_t create_event(); +__kernel void k3() { + event_t e1 = create_event(); + event_t e2 = create_event(); + event_t e[] = {e1, e2}; +} + diff --git a/test/SemaOpenCL/storageclass.cl b/test/SemaOpenCL/storageclass.cl index a93f8244dcbd..f457cfd1d3f6 100644 --- a/test/SemaOpenCL/storageclass.cl +++ b/test/SemaOpenCL/storageclass.cl @@ -5,7 +5,7 @@ constant int G2 = 0; int G3 = 0; // expected-error{{program scope variable must reside in constant address space}} global int G4 = 0; // expected-error{{program scope variable must reside in constant address space}} -void kernel foo() { +void kernel foo(int x) { // static is not allowed at local scope before CL2.0 static int S1 = 5; // expected-error{{variables in function scope cannot be declared static}} static constant int S2 = 5; // expected-error{{variables in function scope cannot be declared static}} @@ -15,6 +15,12 @@ void kernel foo() { auto int L3 = 7; // expected-error{{OpenCL version 1.2 does not support the 'auto' storage class specifier}} global int L4; // expected-error{{function scope variable cannot be declared in global address space}} + + constant int L5 = x; // expected-error {{initializer element is not a compile-time constant}} + global int *constant L6 = &G4; + private int *constant L7 = &x; // expected-error {{initializer element is not a compile-time constant}} + constant int *constant L8 = &L1; + local int *constant L9 = &L2; // expected-error {{initializer element is not a compile-time constant}} } static void kernel bar() { // expected-error{{kernel functions cannot be declared static}} @@ -29,4 +35,7 @@ void f() { } global int L3; // expected-error{{function scope variable cannot be declared in global address space}} extern constant float L4; + extern local float L5; // expected-error{{extern variable must reside in constant address space}} + static int L6 = 0; // expected-error{{variables in function scope cannot be declared static}} + static int L7; // expected-error{{variables in function scope cannot be declared static}} } diff --git a/test/SemaTemplate/deduction-crash.cpp b/test/SemaTemplate/deduction-crash.cpp index ff7421a910bd..c94c9db94e06 100644 --- a/test/SemaTemplate/deduction-crash.cpp +++ b/test/SemaTemplate/deduction-crash.cpp @@ -2,7 +2,7 @@ // Note that the error count below doesn't matter. We just want to // make sure that the parser doesn't crash. -// CHECK: 16 errors +// CHECK: 17 errors // PR7511 template diff --git a/test/SemaTemplate/default-arguments.cpp b/test/SemaTemplate/default-arguments.cpp index d3e249db7ee2..b5b042c64a71 100644 --- a/test/SemaTemplate/default-arguments.cpp +++ b/test/SemaTemplate/default-arguments.cpp @@ -207,3 +207,19 @@ Y y2; } // end ns1 } // end ns PR26134 + +namespace friends { + namespace ns { + template struct A { + template friend void f(); + template friend struct X; + }; + template void f(); // expected-warning 0-1{{extension}} + template struct X; + A a; + } + namespace ns { + void g() { f(); } + X *p; + } +} diff --git a/test/SemaTemplate/explicit-instantiation.cpp b/test/SemaTemplate/explicit-instantiation.cpp index 010716dd1426..42d9f4d332a9 100644 --- a/test/SemaTemplate/explicit-instantiation.cpp +++ b/test/SemaTemplate/explicit-instantiation.cpp @@ -95,7 +95,7 @@ namespace PR7622 { struct basic_streambuf; template - struct basic_streambuf{friend bob<>()}; // expected-error{{unknown type name 'bob'}} \ + struct basic_streambuf{friend bob<>()}; // expected-error{{no template named 'bob'}} \ // expected-error{{expected member name or ';' after declaration specifiers}} template struct basic_streambuf; } diff --git a/test/SemaTemplate/explicit-specialization-member.cpp b/test/SemaTemplate/explicit-specialization-member.cpp index f302836c7e4b..c0c36808b492 100644 --- a/test/SemaTemplate/explicit-specialization-member.cpp +++ b/test/SemaTemplate/explicit-specialization-member.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify %s -fcxx-exceptions template struct X0 { typedef T* type; @@ -57,3 +57,12 @@ template struct Helper { template void Helper::func<2>() {} // expected-error {{cannot specialize a member}} \ // expected-error {{no function template matches}} } + +namespace SpecLoc { + template struct A { + static int n; // expected-note {{previous}} + static void f(); // expected-note {{previous}} + }; + template<> float A::n; // expected-error {{different type}} + template<> void A::f() throw(); // expected-error {{does not match}} +} diff --git a/test/SemaTemplate/ms-lookup-template-base-classes.cpp b/test/SemaTemplate/ms-lookup-template-base-classes.cpp index 6afc7091260d..a41248ee1b8e 100644 --- a/test/SemaTemplate/ms-lookup-template-base-classes.cpp +++ b/test/SemaTemplate/ms-lookup-template-base-classes.cpp @@ -347,8 +347,7 @@ template struct B : A { }; template struct C : A { // Incorrect form. - NameFromBase m; // expected-error {{unknown type name 'NameFromBase'}} - //expected-error@-1 {{expected member name or ';' after declaration specifiers}} + NameFromBase m; // expected-error {{no template named 'NameFromBase'}} }; } diff --git a/test/SemaTemplate/typo-template-name.cpp b/test/SemaTemplate/typo-template-name.cpp new file mode 100644 index 000000000000..fe5201a8e26c --- /dev/null +++ b/test/SemaTemplate/typo-template-name.cpp @@ -0,0 +1,43 @@ +// RUN: %clang_cc1 -std=c++1z %s -verify -Wno-unused + +namespace InExpr { + namespace A { + void typo_first_a(); // expected-note {{found}} + template void typo_first_b(); // expected-note 2{{declared here}} + } + void testA() { A::typo_first_a(); } // expected-error {{'typo_first_a' does not name a template but is followed by template arguments; did you mean 'typo_first_b'?}} + + namespace B { + void typo_first_b(); // expected-note {{found}} + } + void testB() { B::typo_first_b(); } // expected-error {{'typo_first_b' does not name a template but is followed by template arguments; did you mean 'A::typo_first_b'?}} + + struct Base { + template static void foo(); // expected-note 4{{declared here}} + int n; + }; + struct Derived : Base { + void foo(); // expected-note {{found}} + }; + // We probably don't want to suggest correcting to .Base::foo + void testMember() { Derived().foo(); } // expected-error-re {{does not name a template but is followed by template arguments{{$}}}} + + struct Derived2 : Base { + void goo(); // expected-note {{found}} + }; + void testMember2() { Derived2().goo(); } // expected-error {{member 'goo' of 'InExpr::Derived2' is not a template; did you mean 'foo'?}} + + void no_correction() { + int foo; // expected-note 3{{found}} + + foo(); // expected-error {{'foo' does not name a template but is followed by template arguments; did you mean 'Base::foo'?}} + foo<>(); // expected-error {{'foo' does not name a template but is followed by template arguments; did you mean 'Base::foo'?}} + foo(); // expected-error {{'foo' does not name a template but is followed by template arguments; did you mean 'Base::foo'?}} + + // These are valid expressions. + foo(0); + foo(false); + foo Imports("import", llvm::cl::ZeroOrMore, llvm::cl::desc("Path to a file containing declarations to import")); +static llvm::cl::opt + Direct("direct", llvm::cl::Optional, + llvm::cl::desc("Use the parsed declarations without indirection")); + static llvm::cl::list ClangArgs("Xcc", llvm::cl::ZeroOrMore, llvm::cl::desc("Argument to pass to the CompilerInvocation"), @@ -172,6 +176,14 @@ BuildCompilerInstance(ArrayRef ClangArgv) { return Ins; } +std::unique_ptr +BuildCompilerInstance(ArrayRef ClangArgs) { + std::vector ClangArgv(ClangArgs.size()); + std::transform(ClangArgs.begin(), ClangArgs.end(), ClangArgv.begin(), + [](const std::string &s) -> const char * { return s.data(); }); + return init_convenience::BuildCompilerInstance(ClangArgv); +} + std::unique_ptr BuildASTContext(CompilerInstance &CI, SelectorTable &ST, Builtin::Context &BC) { auto AST = llvm::make_unique( @@ -205,6 +217,21 @@ void AddExternalSource( CI.getASTContext().getTranslationUnitDecl()->setHasExternalVisibleStorage(); } +std::unique_ptr BuildIndirect(std::unique_ptr &CI) { + std::vector ClangArgv(ClangArgs.size()); + std::transform(ClangArgs.begin(), ClangArgs.end(), ClangArgv.begin(), + [](const std::string &s) -> const char * { return s.data(); }); + std::unique_ptr IndirectCI = + init_convenience::BuildCompilerInstance(ClangArgv); + auto ST = llvm::make_unique(); + auto BC = llvm::make_unique(); + std::unique_ptr AST = + init_convenience::BuildASTContext(*IndirectCI, *ST, *BC); + IndirectCI->setASTContext(AST.release()); + AddExternalSource(*IndirectCI, CI); + return IndirectCI; +} + llvm::Error ParseSource(const std::string &Path, CompilerInstance &CI, CodeGenerator &CG) { SourceManager &SM = CI.getSourceManager(); @@ -231,7 +258,8 @@ Parse(const std::string &Path, std::unique_ptr AST = init_convenience::BuildASTContext(*CI, *ST, *BC); CI->setASTContext(AST.release()); - AddExternalSource(*CI, Imports); + if (Imports.size()) + AddExternalSource(*CI, Imports); auto LLVMCtx = llvm::make_unique(); std::unique_ptr CG = @@ -268,8 +296,21 @@ int main(int argc, const char **argv) { ImportCIs.push_back(std::move(*ImportCI)); } } + std::vector> IndirectCIs; + if (!Direct) { + for (auto &ImportCI : ImportCIs) { + llvm::Expected> IndirectCI = + BuildIndirect(ImportCI); + if (auto E = IndirectCI.takeError()) { + llvm::errs() << llvm::toString(std::move(E)); + exit(-1); + } else { + IndirectCIs.push_back(std::move(*IndirectCI)); + } + } + } llvm::Expected> ExpressionCI = - Parse(Expression, ImportCIs); + Parse(Expression, Direct ? ImportCIs : IndirectCIs); if (auto E = ExpressionCI.takeError()) { llvm::errs() << llvm::toString(std::move(E)); exit(-1); @@ -277,3 +318,4 @@ int main(int argc, const char **argv) { return 0; } } + diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index c251d83e2097..9c795ae9c5b7 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -7479,6 +7479,35 @@ unsigned clang_Cursor_isVariadic(CXCursor C) { return 0; } +unsigned clang_Cursor_isExternalSymbol(CXCursor C, + CXString *language, CXString *definedIn, + unsigned *isGenerated) { + if (!clang_isDeclaration(C.kind)) + return 0; + + const Decl *D = getCursorDecl(C); + + auto getExternalSymAttr = [](const Decl *D) -> ExternalSourceSymbolAttr* { + if (auto *attr = D->getAttr()) + return attr; + if (auto *dcd = dyn_cast(D->getDeclContext())) { + if (auto *attr = dcd->getAttr()) + return attr; + } + return nullptr; + }; + if (auto *attr = getExternalSymAttr(D)) { + if (language) + *language = cxstring::createDup(attr->getLanguage()); + if (definedIn) + *definedIn = cxstring::createDup(attr->getDefinedIn()); + if (isGenerated) + *isGenerated = attr->getGeneratedDeclaration(); + return 1; + } + return 0; +} + CXSourceRange clang_Cursor_getCommentRange(CXCursor C) { if (!clang_isDeclaration(C.kind)) return clang_getNullRange(); diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports index 895dd804b008..d9a406e5741b 100644 --- a/tools/libclang/libclang.exports +++ b/tools/libclang/libclang.exports @@ -35,6 +35,7 @@ clang_Cursor_getReceiverType clang_Cursor_isAnonymous clang_Cursor_isBitField clang_Cursor_isDynamicCall +clang_Cursor_isExternalSymbol clang_Cursor_isNull clang_Cursor_isObjCOptional clang_Cursor_isVariadic diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp index 9b833a96f16a..076041406c87 100644 --- a/unittests/Format/FormatTest.cpp +++ b/unittests/Format/FormatTest.cpp @@ -342,7 +342,7 @@ TEST_F(FormatTest, FormatIfWithoutCompoundStatement) { verifyFormat("if (a)\n if (b) {\n f();\n }\ng();"); FormatStyle AllowsMergedIf = getLLVMStyle(); - AllowsMergedIf.AlignEscapedNewlinesLeft = true; + AllowsMergedIf.AlignEscapedNewlines = FormatStyle::ENAS_Left; AllowsMergedIf.AllowShortIfStatementsOnASingleLine = true; verifyFormat("if (a)\n" " // comment\n" @@ -2106,7 +2106,7 @@ TEST_F(FormatTest, LayoutStatementsAroundPreprocessorDirectives) { verifyIncompleteFormat("void f(\n" "#if A\n" - " );\n" + ");\n" "#else\n" "#endif"); } @@ -2591,6 +2591,60 @@ TEST_F(FormatTest, BreakingBeforeNonAssigmentOperators) { Style); } +TEST_F(FormatTest, AllowBinPackingInsideArguments) { + FormatStyle Style = getLLVMStyle(); + Style.BreakBeforeBinaryOperators = FormatStyle::BOS_NonAssignment; + Style.BinPackArguments = false; + Style.ColumnLimit = 40; + verifyFormat("void test() {\n" + " someFunction(\n" + " this + argument + is + quite\n" + " + long + so + it + gets + wrapped\n" + " + but + remains + bin - packed);\n" + "}", + Style); + verifyFormat("void test() {\n" + " someFunction(arg1,\n" + " this + argument + is\n" + " + quite + long + so\n" + " + it + gets + wrapped\n" + " + but + remains + bin\n" + " - packed,\n" + " arg3);\n" + "}", + Style); + verifyFormat("void test() {\n" + " someFunction(\n" + " arg1,\n" + " this + argument + has\n" + " + anotherFunc(nested,\n" + " calls + whose\n" + " + arguments\n" + " + are + also\n" + " + wrapped,\n" + " in + addition)\n" + " + to + being + bin - packed,\n" + " arg3);\n" + "}", + Style); + + Style.BreakBeforeBinaryOperators = FormatStyle::BOS_None; + verifyFormat("void test() {\n" + " someFunction(\n" + " arg1,\n" + " this + argument + has +\n" + " anotherFunc(nested,\n" + " calls + whose +\n" + " arguments +\n" + " are + also +\n" + " wrapped,\n" + " in + addition) +\n" + " to + being + bin - packed,\n" + " arg3);\n" + "}", + Style); +} + TEST_F(FormatTest, ConstructorInitializers) { verifyFormat("Constructor() : Initializer(FitsOnTheLine) {}"); verifyFormat("Constructor() : Inttializer(FitsOnTheLine) {}", @@ -4421,7 +4475,7 @@ TEST_F(FormatTest, WrapsTemplateDeclarations) { EXPECT_EQ("static_cast *>(\n" "\n" - " );", + ");", format("static_cast*>(\n" "\n" @@ -6423,7 +6477,7 @@ TEST_F(FormatTest, BreaksStringLiterals) { EXPECT_EQ("\"some text other\";", format("\"some text other\";", Style)); FormatStyle AlignLeft = getLLVMStyleWithColumns(12); - AlignLeft.AlignEscapedNewlinesLeft = true; + AlignLeft.AlignEscapedNewlines = FormatStyle::ENAS_Left; EXPECT_EQ("#define A \\\n" " \"some \" \\\n" " \"text \" \\\n" @@ -6513,7 +6567,7 @@ TEST_F(FormatTest, BreaksStringLiteralsWithin_TMacro) { "#if !TEST\n" " _T(\"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXn\")\n" "#endif\n" - " );", + ");", format("f(\n" "#if !TEST\n" "_T(\"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXn\")\n" @@ -6824,7 +6878,7 @@ TEST_F(FormatTest, ConfigurableUseOfTab) { FormatStyle Tab = getLLVMStyleWithColumns(42); Tab.IndentWidth = 8; Tab.UseTab = FormatStyle::UT_Always; - Tab.AlignEscapedNewlinesLeft = true; + Tab.AlignEscapedNewlines = FormatStyle::ENAS_Left; EXPECT_EQ("if (aaaaaaaa && // q\n" " bb)\t\t// w\n" @@ -7605,14 +7659,21 @@ TEST_F(FormatTest, AlignConsecutiveAssignments) { "int oneTwoThree = 123;\n" "int oneTwo = 12;", Alignment)); - Alignment.AlignEscapedNewlinesLeft = true; + Alignment.AlignEscapedNewlines = FormatStyle::ENAS_DontAlign; + verifyFormat("#define A \\\n" + " int aaaa = 12; \\\n" + " int b = 23; \\\n" + " int ccc = 234; \\\n" + " int dddddddddd = 2345;", + Alignment); + Alignment.AlignEscapedNewlines = FormatStyle::ENAS_Left; verifyFormat("#define A \\\n" " int aaaa = 12; \\\n" " int b = 23; \\\n" " int ccc = 234; \\\n" " int dddddddddd = 2345;", Alignment); - Alignment.AlignEscapedNewlinesLeft = false; + Alignment.AlignEscapedNewlines = FormatStyle::ENAS_Right; verifyFormat("#define A " " \\\n" " int aaaa = 12; " @@ -7879,14 +7940,21 @@ TEST_F(FormatTest, AlignConsecutiveDeclarations) { "}", Alignment)); Alignment.AlignConsecutiveAssignments = false; - Alignment.AlignEscapedNewlinesLeft = true; + Alignment.AlignEscapedNewlines = FormatStyle::ENAS_DontAlign; + verifyFormat("#define A \\\n" + " int aaaa = 12; \\\n" + " float b = 23; \\\n" + " const int ccc = 234; \\\n" + " unsigned dddddddddd = 2345;", + Alignment); + Alignment.AlignEscapedNewlines = FormatStyle::ENAS_Left; verifyFormat("#define A \\\n" " int aaaa = 12; \\\n" " float b = 23; \\\n" " const int ccc = 234; \\\n" " unsigned dddddddddd = 2345;", Alignment); - Alignment.AlignEscapedNewlinesLeft = false; + Alignment.AlignEscapedNewlines = FormatStyle::ENAS_Right; Alignment.ColumnLimit = 30; verifyFormat("#define A \\\n" " int aaaa = 12; \\\n" @@ -8671,7 +8739,6 @@ TEST_F(FormatTest, GetsCorrectBasedOnStyle) { TEST_F(FormatTest, ParsesConfigurationBools) { FormatStyle Style = {}; Style.Language = FormatStyle::LK_Cpp; - CHECK_PARSE_BOOL(AlignEscapedNewlinesLeft); CHECK_PARSE_BOOL(AlignOperands); CHECK_PARSE_BOOL(AlignTrailingComments); CHECK_PARSE_BOOL(AlignConsecutiveAssignments); @@ -8794,6 +8861,19 @@ TEST_F(FormatTest, ParsesConfiguration) { CHECK_PARSE("AlignAfterOpenBracket: true", AlignAfterOpenBracket, FormatStyle::BAS_Align); + Style.AlignEscapedNewlines = FormatStyle::ENAS_Left; + CHECK_PARSE("AlignEscapedNewlines: DontAlign", AlignEscapedNewlines, + FormatStyle::ENAS_DontAlign); + CHECK_PARSE("AlignEscapedNewlines: Left", AlignEscapedNewlines, + FormatStyle::ENAS_Left); + CHECK_PARSE("AlignEscapedNewlines: Right", AlignEscapedNewlines, + FormatStyle::ENAS_Right); + // For backward compatibility: + CHECK_PARSE("AlignEscapedNewlinesLeft: true", AlignEscapedNewlines, + FormatStyle::ENAS_Left); + CHECK_PARSE("AlignEscapedNewlinesLeft: false", AlignEscapedNewlines, + FormatStyle::ENAS_Right); + Style.UseTab = FormatStyle::UT_ForIndentation; CHECK_PARSE("UseTab: Never", UseTab, FormatStyle::UT_Never); CHECK_PARSE("UseTab: ForIndentation", UseTab, FormatStyle::UT_ForIndentation); @@ -9559,7 +9639,7 @@ TEST_F(FormatTest, FormatsLambdas) { // Other corner cases. verifyFormat("void f() {\n" " bar([]() {} // Did not respect SpacesBeforeTrailingComments\n" - " );\n" + " );\n" "}"); // Lambdas created through weird macros. diff --git a/unittests/Format/FormatTestJS.cpp b/unittests/Format/FormatTestJS.cpp index 9144fe17e9ec..ff28f304be99 100644 --- a/unittests/Format/FormatTestJS.cpp +++ b/unittests/Format/FormatTestJS.cpp @@ -367,6 +367,25 @@ TEST_F(FormatTestJS, GoogScopes) { "});"); } +TEST_F(FormatTestJS, IIFEs) { + // Internal calling parens; no semi. + verifyFormat("(function() {\n" + "var a = 1;\n" + "}())"); + // External calling parens; no semi. + verifyFormat("(function() {\n" + "var b = 2;\n" + "})()"); + // Internal calling parens; with semi. + verifyFormat("(function() {\n" + "var c = 3;\n" + "}());"); + // External calling parens; with semi. + verifyFormat("(function() {\n" + "var d = 4;\n" + "})();"); +} + TEST_F(FormatTestJS, GoogModules) { verifyFormat("goog.module('this.is.really.absurdly.long');", getGoogleJSStyleWithColumns(40)); @@ -451,6 +470,16 @@ TEST_F(FormatTestJS, FormatsFreestandingFunctions) { " inner2(a, b);\n" "}"); verifyFormat("function f() {}"); + verifyFormat("function aFunction() {}\n" + "(function f() {\n" + " var x = 1;\n" + "}());\n"); + // Known issue: this should wrap after {}, but calculateBraceTypes + // misclassifies the first braces as a BK_BracedInit. + verifyFormat("function aFunction(){} {\n" + " let x = 1;\n" + " console.log(x);\n" + "}\n"); } TEST_F(FormatTestJS, GeneratorFunctions) { @@ -519,6 +548,39 @@ TEST_F(FormatTestJS, AsyncFunctions) { " // Comment.\n" " return async.then();\n" "}\n"); + verifyFormat("for async (const x of y) {\n" + " console.log(x);\n" + "}\n"); + verifyFormat("function asyncLoop() {\n" + " for async (const x of y) {\n" + " console.log(x);\n" + " }\n" + "}\n"); + +} + +TEST_F(FormatTestJS, FunctionParametersTrailingComma) { + verifyFormat("function trailingComma(\n" + " p1,\n" + " p2,\n" + " p3,\n" + ") {\n" + " a; //\n" + "}\n", + "function trailingComma(p1, p2, p3,) {\n" + " a; //\n" + "}\n"); + verifyFormat("trailingComma(\n" + " p1,\n" + " p2,\n" + " p3,\n" + ");\n", + "trailingComma(p1, p2, p3,);\n"); + verifyFormat("trailingComma(\n" + " p1 // hello\n" + ");\n", + "trailingComma(p1 // hello\n" + ");\n"); } TEST_F(FormatTestJS, ArrayLiterals) { @@ -662,7 +724,7 @@ TEST_F(FormatTestJS, FunctionLiterals) { "})\n" " .doSomethingElse(\n" " // break\n" - " );"); + " );"); Style.ColumnLimit = 33; verifyFormat("f({a: function() { return 1; }});", Style); @@ -829,7 +891,7 @@ TEST_F(FormatTestJS, ArrowFunctions) { "})\n" " .doSomethingElse(\n" " // break\n" - " );"); + " );"); } TEST_F(FormatTestJS, ReturnStatements) { @@ -1770,6 +1832,8 @@ TEST_F(FormatTestJS, NonNullAssertionOperator) { " .foo()!\n" " .foo()!;\n", getGoogleJSStyleWithColumns(20)); + verifyFormat("let x = namespace!;\n"); + verifyFormat("return !!x;\n"); } TEST_F(FormatTestJS, Conditional) { @@ -1785,6 +1849,7 @@ TEST_F(FormatTestJS, ImportComments) { verifyFormat("import {x} from 'x'; // from some location", getGoogleJSStyleWithColumns(25)); verifyFormat("// taze: x from 'location'", getGoogleJSStyleWithColumns(10)); + verifyFormat("/// ", getGoogleJSStyleWithColumns(10)); } TEST_F(FormatTestJS, Exponentiation) { diff --git a/unittests/Format/FormatTestSelective.cpp b/unittests/Format/FormatTestSelective.cpp index 8046d7fab2dd..9ee87b34c217 100644 --- a/unittests/Format/FormatTestSelective.cpp +++ b/unittests/Format/FormatTestSelective.cpp @@ -325,7 +325,7 @@ TEST_F(FormatTestSelective, WrongIndent) { } TEST_F(FormatTestSelective, AlwaysFormatsEntireMacroDefinitions) { - Style.AlignEscapedNewlinesLeft = true; + Style.AlignEscapedNewlines = FormatStyle::ENAS_Left; EXPECT_EQ("int i;\n" "#define A \\\n" " int i; \\\n" @@ -467,7 +467,7 @@ TEST_F(FormatTestSelective, ReformatRegionAdjustsIndent) { TEST_F(FormatTestSelective, UnderstandsTabs) { Style.IndentWidth = 8; Style.UseTab = FormatStyle::UT_Always; - Style.AlignEscapedNewlinesLeft = true; + Style.AlignEscapedNewlines = FormatStyle::ENAS_Left; EXPECT_EQ("void f() {\n" "\tf();\n" "\tg();\n" diff --git a/unittests/Tooling/RecursiveASTVisitorTest.cpp b/unittests/Tooling/RecursiveASTVisitorTest.cpp index 7e08f9619c1c..269bdbb34ab1 100644 --- a/unittests/Tooling/RecursiveASTVisitorTest.cpp +++ b/unittests/Tooling/RecursiveASTVisitorTest.cpp @@ -52,6 +52,14 @@ TEST(RecursiveASTVisitor, TraverseLambdaBodyCanBeOverridden) { EXPECT_TRUE(Visitor.allBodiesHaveBeenTraversed()); } +TEST(RecursiveASTVisitor, VisitsAttributedLambdaExpr) { + LambdaExprVisitor Visitor; + Visitor.ExpectMatch("", 1, 12); + EXPECT_TRUE(Visitor.runOver( + "void f() { [] () __attribute__ (( fastcall )) { return; }(); }", + LambdaExprVisitor::Lang_CXX14)); +} + // Matches the (optional) capture-default of a lambda-introducer. class LambdaDefaultCaptureVisitor : public ExpectedLocationVisitor { diff --git a/unittests/Tooling/RefactoringCallbacksTest.cpp b/unittests/Tooling/RefactoringCallbacksTest.cpp index ad8aa8f98feb..e226522a70f4 100644 --- a/unittests/Tooling/RefactoringCallbacksTest.cpp +++ b/unittests/Tooling/RefactoringCallbacksTest.cpp @@ -7,10 +7,10 @@ // //===----------------------------------------------------------------------===// -#include "clang/Tooling/RefactoringCallbacks.h" #include "RewriterTestContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/ASTMatchers/ASTMatchers.h" +#include "clang/Tooling/RefactoringCallbacks.h" #include "gtest/gtest.h" namespace clang { @@ -19,11 +19,10 @@ namespace tooling { using namespace ast_matchers; template -void expectRewritten(const std::string &Code, - const std::string &Expected, - const T &AMatcher, - RefactoringCallback &Callback) { - MatchFinder Finder; +void expectRewritten(const std::string &Code, const std::string &Expected, + const T &AMatcher, RefactoringCallback &Callback) { + std::map FileToReplace; + ASTMatchRefactorer Finder(FileToReplace); Finder.addMatcher(AMatcher, &Callback); std::unique_ptr Factory( tooling::newFrontendActionFactory(&Finder)); @@ -31,7 +30,7 @@ void expectRewritten(const std::string &Code, << "Parsing error in \"" << Code << "\""; RewriterTestContext Context; FileID ID = Context.createInMemoryFile("input.cc", Code); - EXPECT_TRUE(tooling::applyAllReplacements(Callback.getReplacements(), + EXPECT_TRUE(tooling::applyAllReplacements(FileToReplace["input.cc"], Context.Rewrite)); EXPECT_EQ(Expected, Context.getRewrittenText(ID)); } @@ -61,18 +60,18 @@ TEST(RefactoringCallbacksTest, ReplacesInteger) { std::string Code = "void f() { int i = 1; }"; std::string Expected = "void f() { int i = 2; }"; ReplaceStmtWithText Callback("id", "2"); - expectRewritten(Code, Expected, id("id", expr(integerLiteral())), - Callback); + expectRewritten(Code, Expected, id("id", expr(integerLiteral())), Callback); } TEST(RefactoringCallbacksTest, ReplacesStmtWithStmt) { std::string Code = "void f() { int i = false ? 1 : i * 2; }"; std::string Expected = "void f() { int i = i * 2; }"; ReplaceStmtWithStmt Callback("always-false", "should-be"); - expectRewritten(Code, Expected, - id("always-false", conditionalOperator( - hasCondition(cxxBoolLiteral(equals(false))), - hasFalseExpression(id("should-be", expr())))), + expectRewritten( + Code, Expected, + id("always-false", + conditionalOperator(hasCondition(cxxBoolLiteral(equals(false))), + hasFalseExpression(id("should-be", expr())))), Callback); } @@ -80,10 +79,10 @@ TEST(RefactoringCallbacksTest, ReplacesIfStmt) { std::string Code = "bool a; void f() { if (a) f(); else a = true; }"; std::string Expected = "bool a; void f() { f(); }"; ReplaceIfStmtWithItsBody Callback("id", true); - expectRewritten(Code, Expected, - id("id", ifStmt( - hasCondition(implicitCastExpr(hasSourceExpression( - declRefExpr(to(varDecl(hasName("a"))))))))), + expectRewritten( + Code, Expected, + id("id", ifStmt(hasCondition(implicitCastExpr(hasSourceExpression( + declRefExpr(to(varDecl(hasName("a"))))))))), Callback); } @@ -92,9 +91,63 @@ TEST(RefactoringCallbacksTest, RemovesEntireIfOnEmptyElse) { std::string Expected = "void f() { }"; ReplaceIfStmtWithItsBody Callback("id", false); expectRewritten(Code, Expected, - id("id", ifStmt(hasCondition(cxxBoolLiteral(equals(false))))), - Callback); + id("id", ifStmt(hasCondition(cxxBoolLiteral(equals(false))))), + Callback); } +TEST(RefactoringCallbacksTest, TemplateJustText) { + std::string Code = "void f() { int i = 1; }"; + std::string Expected = "void f() { FOO }"; + auto Callback = ReplaceNodeWithTemplate::create("id", "FOO"); + EXPECT_FALSE(Callback.takeError()); + expectRewritten(Code, Expected, id("id", declStmt()), **Callback); +} + +TEST(RefactoringCallbacksTest, TemplateSimpleSubst) { + std::string Code = "void f() { int i = 1; }"; + std::string Expected = "void f() { long x = 1; }"; + auto Callback = ReplaceNodeWithTemplate::create("decl", "long x = ${init}"); + EXPECT_FALSE(Callback.takeError()); + expectRewritten(Code, Expected, + id("decl", varDecl(hasInitializer(id("init", expr())))), + **Callback); +} + +TEST(RefactoringCallbacksTest, TemplateLiteral) { + std::string Code = "void f() { int i = 1; }"; + std::string Expected = "void f() { string x = \"$-1\"; }"; + auto Callback = ReplaceNodeWithTemplate::create("decl", + "string x = \"$$-${init}\""); + EXPECT_FALSE(Callback.takeError()); + expectRewritten(Code, Expected, + id("decl", varDecl(hasInitializer(id("init", expr())))), + **Callback); +} + +static void ExpectStringError(const std::string &Expected, + llvm::Error E) { + std::string Found; + handleAllErrors(std::move(E), [&](const llvm::StringError &SE) { + llvm::raw_string_ostream Stream(Found); + SE.log(Stream); + }); + EXPECT_EQ(Expected, Found); +} + +TEST(RefactoringCallbacksTest, TemplateUnterminated) { + auto Callback = ReplaceNodeWithTemplate::create("decl", + "string x = \"$$-${init\""); + ExpectStringError("Unterminated ${...} in replacement template near ${init\"", + Callback.takeError()); +} + +TEST(RefactoringCallbacksTest, TemplateUnknownDollar) { + auto Callback = ReplaceNodeWithTemplate::create("decl", + "string x = \"$<"); + ExpectStringError("Invalid $ in replacement template near $<", + Callback.takeError()); +} + + } // end namespace ast_matchers } // end namespace clang diff --git a/www/cxx_dr_status.html b/www/cxx_dr_status.html index a01e0dd8dddb..b03b3f0ef9c2 100644 --- a/www/cxx_dr_status.html +++ b/www/cxx_dr_status.html @@ -28,7 +28,7 @@

C++ Defect Report Support in Clang

-

Last updated: $Date: 2017-03-17 22:41:20 +0100 (Fri, 17 Mar 2017) $

+

Last updated: $Date: 2017-05-10 00:21:24 +0200 (Wed, 10 May 2017) $

C++ defect report implementation status

@@ -589,7 +589,7 @@
92 - WP + CD4 Should exception-specifications be part of the type system? Clang 4 (C++17 onwards) @@ -935,11 +935,11 @@ Accessibility and ambiguity N/A - - 150 - open + + 150 + DR Template template parameters and default arguments - Not resolved + Unknown 151 @@ -1310,7 +1310,7 @@ accessible? 212 - DR + CD4 Implicit instantiation is not described clearly enough Unknown @@ -1466,7 +1466,7 @@ accessible? 238 - DR + CD4 Precision and accuracy constraints on floating point Unknown @@ -1490,7 +1490,7 @@ accessible? 242 - DR + CD4 Interpretation of old-style casts Unknown @@ -2019,7 +2019,7 @@ of class templates 330 - DRWP + CD4 Qualification conversions and pointers to arrays of pointers Unknown @@ -2397,7 +2397,7 @@ of class templates 393 - DRWP + CD4 Pointer to array of unknown bound in template argument list in parameter Unknown @@ -3017,7 +3017,7 @@ of class templates 496 CD3 Is a volatile-qualified type really a POD? - No + Superseded by dr2094 497 @@ -3587,7 +3587,7 @@ and POD class 591 - DRWP + CD4 When a dependent base class is the current instantiation No @@ -3695,7 +3695,7 @@ and POD class 609 - DRWP + CD4 What is a “top-level” cv-qualifier? Unknown @@ -5735,7 +5735,7 @@ and POD class 987 - DRWP + CD4 Which declarations introduce namespace members? Unknown @@ -5939,7 +5939,7 @@ and POD class 1021 - DRWP + CD4 Definitions of namespace members Unknown @@ -6509,7 +6509,7 @@ and POD class 1116 - DRWP + CD4 Aliasing of union members Unknown @@ -7295,7 +7295,7 @@ and POD class 1247 - DRWP + CD4 Restriction on alias name appearing in type-id Unknown @@ -7457,7 +7457,7 @@ and POD class 1274 - DRWP + CD4 Common nonterminal for expression and braced-init-list Unknown @@ -7517,7 +7517,7 @@ and POD class 1284 - DR + CD4 Should the lifetime of an array be independent of that of its elements? Unknown @@ -7565,7 +7565,7 @@ and POD class 1292 - DRWP + CD4 Dependent calls with braced-init-lists containing a pack expansion Unknown @@ -7667,7 +7667,7 @@ and POD class 1309 - DRWP + CD4 Incorrect note regarding lookup of a member of the current instantiation Unknown @@ -7703,7 +7703,7 @@ and POD class 1315 - DR + CD4 Restrictions on non-type template arguments in partial specializations Partial @@ -7841,7 +7841,7 @@ and POD class 1338 - DRWP + CD4 Aliasing and allocation functions Unknown @@ -7870,8 +7870,8 @@ and POD class Not resolved - 1343 - tentatively ready + 1343 + DR Sequencing of non-class initialization Unknown @@ -7919,7 +7919,7 @@ and POD class 1351 - DRWP + CD4 Problems with implicitly-declared exception-specifications Unknown @@ -7949,7 +7949,7 @@ and POD class 1356 - DRWP + CD4 Exception specifications of copy assignment operators with virtual bases Unknown @@ -8159,7 +8159,7 @@ and POD class 1391 - DRWP + CD4 Conversions to parameter types with non-deduced template arguments Partial @@ -8182,8 +8182,8 @@ and POD class Unknown - 1395 - ready + 1395 + DR Partial ordering of variadic templates reconsidered Unknown @@ -8195,7 +8195,7 @@ and POD class 1397 - DRWP + CD4 Class completeness in non-static data member initializers Unknown @@ -8489,7 +8489,7 @@ and POD class 1446 - DRWP + CD4 Member function with no ref-qualifier and non-member function with rvalue reference Unknown @@ -8603,7 +8603,7 @@ and POD class 1465 - DRWP + CD4 noexcept and std::bad_array_new_length Unknown @@ -8615,7 +8615,7 @@ and POD class 1467 - DRWP + CD4 List-initialization of aggregate from same-type object Clang 3.7 (C++11 onwards) @@ -8717,7 +8717,7 @@ and POD class 1484 - DRWP + CD4 Unused local classes of function templates Unknown @@ -8753,7 +8753,7 @@ and POD class 1490 - DRWP + CD4 List-initialization from a string literal Clang 3.7 (C++11 onwards) @@ -8765,7 +8765,7 @@ and POD class 1492 - DRWP + CD4 Exception specifications on template destructors Unknown @@ -8789,7 +8789,7 @@ and POD class 1496 - DR + CD4 Triviality with deleted and missing default constructors Unknown @@ -8921,7 +8921,7 @@ and POD class 1518 - DRWP + CD4 Explicit default constructors and copy-list-initialization Clang 4 @@ -9125,7 +9125,7 @@ and POD class 1552 - DRWP + CD4 exception-specifications and defaulted special member functions Unknown @@ -9161,7 +9161,7 @@ and POD class 1558 - DRWP + CD4 Unused arguments in alias template specializations Unknown @@ -9201,11 +9201,11 @@ and POD class Template argument deduction from an initializer list Unknown - - 1565 - drafting + + 1565 + NAD Copy elision and lifetime of initializer_list underlying array - Not resolved + Unknown 1566 @@ -9239,19 +9239,19 @@ and POD class 1571 - DRWP + CD4 cv-qualification for indirect reference binding via conversion function Unknown 1572 - DRWP + CD4 Incorrect example for rvalue reference binding via conversion function Unknown 1573 - DRWP + CD4 Inherited constructor characteristics Clang 3.9 @@ -9347,7 +9347,7 @@ and POD class 1589 - DRWP + CD4 Ambiguous ranking of list-initialization sequences Clang 3.7 (C++11 onwards) @@ -9359,7 +9359,7 @@ and POD class 1591 - DRWP + CD4 Deducing array bound and element type from initializer list Unknown @@ -9389,7 +9389,7 @@ and POD class 1596 - DRWP + CD4 Non-array objects as array[1] Unknown @@ -9413,7 +9413,7 @@ and POD class 1600 - DRWP + CD4 Erroneous reference initialization in example Unknown @@ -9431,7 +9431,7 @@ and POD class 1603 - DRWP + CD4 Errors resulting from giving unnamed namespaces internal linkage Unknown @@ -9497,13 +9497,13 @@ and POD class 1614 - DRWP + CD4 Address of pure virtual function vs odr-use Unknown 1615 - DRWP + CD4 Alignment of types, variables, and members Unknown @@ -9543,11 +9543,11 @@ and POD class Member initializers in anonymous unions Not resolved - + 1622 - drafting + ready Empty aggregate initializer for union - Not resolved + Unknown 1623 @@ -9593,13 +9593,13 @@ and POD class 1630 - DRWP + CD4 Multiple default constructor templates Unknown 1631 - DRWP + CD4 Incorrect overload resolution for single-element initializer-list Clang 3.7 @@ -9611,7 +9611,7 @@ and POD class 1633 - DRWP + CD4 Copy-initialization in member initialization Unknown @@ -9641,13 +9641,13 @@ and POD class 1638 - DR + CD4 Declaring an explicit specialization of a scoped enumeration Yes 1639 - DRWP + CD4 exception-specifications and pointer/pointer-to-member expressions Unknown @@ -9683,7 +9683,7 @@ and POD class 1645 - DRWP + CD4 Identical inheriting constructors via default arguments Clang 3.9 @@ -9725,13 +9725,13 @@ and POD class 1652 - DRWP + CD4 Object addresses in constexpr expressions Unknown 1653 - WP + CD4 Removing deprecated increment of bool Clang 4 (C++17 onwards) @@ -9755,7 +9755,7 @@ and POD class 1657 - WP + CD4 Attributes for namespaces and enumerators Unknown @@ -9845,7 +9845,7 @@ and POD class 1672 - DRWP + CD4 Layout compatibility with multiple empty bases Unknown @@ -9873,11 +9873,11 @@ and POD class auto return type for allocation and deallocation functions Not resolved - + 1677 - drafting + ready Constant initialization via aggregate initialization - Not resolved + Unknown 1678 @@ -9911,7 +9911,7 @@ and POD class 1683 - DRWP + CD4 Incorrect example after constexpr changes Unknown @@ -9929,7 +9929,7 @@ and POD class 1686 - DRWP + CD4 Which variables are “explicitly declared const?” Unknown @@ -9977,7 +9977,7 @@ and POD class 1694 - DRWP + CD4 Restriction on reference to temporary as a constant expression Unknown @@ -9989,7 +9989,7 @@ and POD class 1696 - DRWP + CD4 Temporary lifetime and non-static data member initializers Unknown @@ -10043,7 +10043,7 @@ and POD class 1705 - DRWP + CD4 Unclear specification of “more specialized” Unknown @@ -10061,7 +10061,7 @@ and POD class 1708 - DRWP + CD4 overly-strict requirements for names with C language linkage Unknown @@ -10085,7 +10085,7 @@ and POD class 1712 - DRWP + CD4 constexpr variable template declarations Unknown @@ -10103,7 +10103,7 @@ and POD class 1715 - DRWP + CD4 Access and inherited constructor templates Clang 3.9 @@ -10127,7 +10127,7 @@ and POD class 1719 - DRWP + CD4 Layout compatibility and cv-qualification revisited Unknown @@ -10145,7 +10145,7 @@ and POD class 1722 - DRWP + CD4 Should lambda to function pointer conversion function be noexcept? Unknown @@ -10217,7 +10217,7 @@ and POD class 1734 - DR + CD4 Nontrivial deleted copy functions Unknown @@ -10229,7 +10229,7 @@ and POD class 1736 - DRWP + CD4 Inheriting constructor templates in a local class Clang 3.9 @@ -10277,7 +10277,7 @@ and POD class 1744 - DRWP + CD4 Unordered initialization for variable template specializations Unknown @@ -10301,7 +10301,7 @@ and POD class 1748 - DRWP + CD4 Placement new with a null pointer Clang 3.7 @@ -10313,25 +10313,25 @@ and POD class 1750 - DRWP + CD4 “Argument” vs “parameter” Unknown 1751 - DRWP + CD4 Non-trivial operations vs non-trivial initialization Unknown 1752 - DRWP + CD4 Right-recursion in mem-initializer-list Unknown 1753 - DRWP + CD4 decltype-specifier in nested-name-specifier of destructor Unknown @@ -10349,19 +10349,19 @@ and POD class 1756 - DRWP + CD4 Direct-list-initialization of a non-class object Clang 3.7 1757 - DRWP + CD4 Const integral subobjects Unknown 1758 - DRWP + CD4 Explicit conversion in copy/move list initialization Clang 3.7 @@ -10409,7 +10409,7 @@ and POD class 1766 - DRWP + CD4 Values outside the range of the values of an enumeration Unknown @@ -10457,7 +10457,7 @@ and POD class 1774 - DRWP + CD4 Discrepancy between subobject destruction and stack unwinding Unknown @@ -10469,13 +10469,13 @@ and POD class 1776 - DRWP + CD4 Replacement of class objects containing reference members Unknown 1777 - DRWP + CD4 Empty pack expansion in dynamic-exception-specification Unknown @@ -10487,13 +10487,13 @@ and POD class 1779 - DRWP + CD4 Type dependency of __func__ Unknown 1780 - DRWP + CD4 Explicit instantiation/specialization of generic lambda operator() Unknown @@ -10505,7 +10505,7 @@ and POD class 1782 - DRWP + CD4 Form of initialization for nullptr_t to bool conversion Unknown @@ -10541,7 +10541,7 @@ and POD class 1788 - DRWP + CD4 Sized deallocation of array of non-class type Unknown @@ -10559,7 +10559,7 @@ and POD class 1791 - DRWP + CD4 Incorrect restrictions on cv-qualifier-seq and ref-qualifier Unknown @@ -10571,7 +10571,7 @@ and POD class 1793 - DRWP + CD4 thread_local in explicit specializations Unknown @@ -10583,19 +10583,19 @@ and POD class 1795 - DRWP + CD4 Disambiguating original-namespace-definition and extension-namespace-definition Unknown 1796 - DRWP + CD4 Is all-bits-zero for null characters a meaningful requirement? Unknown 1797 - DRWP + CD4 Are all bit patterns of unsigned char distinct numbers? Unknown @@ -10607,13 +10607,13 @@ and POD class 1799 - DRWP + CD4 mutable and non-explicit const qualification Unknown 1800 - DRWP + CD4 Pointer to member of nested anonymous union Unknown @@ -10625,7 +10625,7 @@ and POD class 1802 - DRWP + CD4 char16_t string literals and surrogate pairs Unknown @@ -10637,25 +10637,25 @@ and POD class 1804 - DRWP + CD4 Partial specialization and friendship Unknown 1805 - DRWP + CD4 Conversions of array operands in conditional-expressions Unknown 1806 - DRWP + CD4 Virtual bases and move-assignment Unknown 1807 - DRWP + CD4 Order of destruction of array elements after an exception Unknown @@ -10667,19 +10667,19 @@ and POD class 1809 - DRWP + CD4 Narrowing and template argument deduction Unknown 1810 - DRWP + CD4 Invalid ud-suffixes Unknown 1811 - DRWP + CD4 Lookup of deallocation function in a virtual destructor definition Unknown @@ -10691,25 +10691,25 @@ and POD class 1813 - DRWP + CD4 Direct vs indirect bases in standard-layout classes Unknown 1814 - DRWP + CD4 Default arguments in lambda-expressions Unknown 1815 - DRWP + CD4 Lifetime extension in aggregate initialization Unknown 1816 - DRWP + CD4 Unclear specification of bit-field values Unknown @@ -10727,7 +10727,7 @@ and POD class 1819 - DRWP + CD4 Acceptable scopes for definition of partial specialization Unknown @@ -10751,19 +10751,19 @@ and POD class 1823 - DRWP + CD4 String literal uniqueness in inline functions Unknown 1824 - DRWP + CD4 Completeness of return type vs point of instantiation Unknown - 1825 - ready + 1825 + DR Partial ordering between variadic and non-variadic function templates Unknown @@ -10793,7 +10793,7 @@ and POD class 1830 - DRWP + CD4 Repeated specifiers Unknown @@ -10805,7 +10805,7 @@ and POD class 1832 - DRWP + CD4 Casting to incomplete enumeration Unknown @@ -10817,7 +10817,7 @@ and POD class 1834 - DRWP + CD4 Constant initialization binding a reference to an xvalue Unknown @@ -10841,7 +10841,7 @@ and POD class 1838 - DRWP + CD4 Definition via unqualified-id and using-declaration Unknown @@ -10871,7 +10871,7 @@ and POD class 1843 - DRWP + CD4 Bit-field in conditional operator with throw operand Unknown @@ -10889,19 +10889,19 @@ and POD class 1846 - DRWP + CD4 Declaring explicitly-defaulted implicitly-deleted functions Unknown 1847 - DRWP + CD4 Clarifying compatibility during partial ordering Unknown 1848 - DRWP + CD4 Parenthesized constructor and destructor declarators Unknown @@ -10913,19 +10913,19 @@ and POD class 1850 - DRWP + CD4 Differences between definition context and point of instantiation Unknown 1851 - DRWP + CD4 decltype(auto) in new-expressions Unknown 1852 - DRWP + CD4 Wording issues regarding decltype(auto) Unknown @@ -10961,7 +10961,7 @@ and POD class 1858 - DRWP + CD4 Comparing pointers to union members Unknown @@ -10971,15 +10971,15 @@ and POD class UTF-16 in char16_t string literals Not resolved - + 1860 - review + ready What is a “direct member?” - Not resolved + Unknown 1861 - DRWP + CD4 Values of a bit-field Unknown @@ -10991,7 +10991,7 @@ and POD class 1863 - DRWP + CD4 Requirements on thrown object type to support std::current_exception() Unknown @@ -11003,13 +11003,13 @@ and POD class 1865 - DRWP + CD4 Pointer arithmetic and multi-level qualification conversions Unknown 1866 - DRWP + CD4 Initializing variant members with non-trivial destructors Unknown @@ -11033,7 +11033,7 @@ and POD class 1870 - DRWP + CD4 Contradictory wording about definitions vs explicit specialization/instantiation Unknown @@ -11045,25 +11045,25 @@ and POD class 1872 - DR + CD4 Instantiations of constexpr templates that cannot appear in constant expressions Unknown 1873 - DRWP + CD4 Protected member access from derived class friends Unknown 1874 - DRWP + CD4 Type vs non-type template parameters with class keyword Unknown 1875 - DRWP + CD4 Reordering declarations in class scope Unknown @@ -11075,13 +11075,13 @@ and POD class 1877 - DRWP + CD4 Return type deduction from return with no operand Unknown 1878 - DRWP + CD4 operator auto template Unknown @@ -11099,13 +11099,13 @@ and POD class 1881 - DRWP + CD4 Standard-layout classes and unnamed bit-fields Unknown 1882 - DRWP + CD4 Reserved names without library use Unknown @@ -11123,25 +11123,25 @@ and POD class 1885 - DRWP + CD4 Return value of a function is underspecified Unknown 1886 - DRWP + CD4 Language linkage for main() Unknown 1887 - DRWP + CD4 Problems with :: as nested-name-specifier Unknown 1888 - DRWP + CD4 Implicitly-declared default constructors and explicit Unknown @@ -11159,13 +11159,13 @@ and POD class 1891 - DRWP + CD4 Move constructor/assignment for closure class Clang 4 1892 - DRWP + CD4 Use of auto in function type Unknown @@ -11183,7 +11183,7 @@ and POD class 1895 - DR + CD4 Deleted conversions in conditional operator operands Unknown @@ -11207,7 +11207,7 @@ and POD class 1899 - DRWP + CD4 Value-dependent constant expressions Unknown @@ -11225,13 +11225,13 @@ and POD class 1902 - DRWP + CD4 What makes a conversion “otherwise ill-formed”? Clang 3.7 1903 - DRWP + CD4 What declarations are introduced by a non-member using-declaration? Unknown @@ -11267,7 +11267,7 @@ and POD class 1909 - DRWP + CD4 Member class template with the same name as the class Yes @@ -11279,7 +11279,7 @@ and POD class 1911 - DRWP + CD4 constexpr constructor with non-literal base class Unknown @@ -11309,7 +11309,7 @@ and POD class 1916 - DRWP + CD4 “Same cv-unqualified type” Unknown @@ -11333,7 +11333,7 @@ and POD class 1920 - DRWP + CD4 Qualification mismatch in pseudo-destructor-name Unknown @@ -11345,7 +11345,7 @@ and POD class 1922 - DRWP + CD4 Injected class template names and default arguments Unknown @@ -11357,19 +11357,19 @@ and POD class 1924 - drafting + review Definition of “literal” and kinds of literals Not resolved 1925 - DRWP + CD4 Bit-field prvalues Unknown 1926 - DRWP + CD4 Potential results of subscript operator Unknown @@ -11387,13 +11387,13 @@ and POD class 1929 - DRWP + CD4 template keyword following namespace nested-name-specifier Unknown 1930 - DR + CD4 init-declarator-list vs member-declarator-list Unknown @@ -11405,7 +11405,7 @@ and POD class 1932 - DR + CD4 Bit-field results of conditional operators Unknown @@ -11453,19 +11453,19 @@ and POD class 1940 - DRWP + CD4 static_assert in anonymous unions Yes 1941 - DRWP + CD4 SFINAE and inherited constructor default arguments Clang 3.9 1942 - DRWP + CD4 Incorrect reference to trailing-return-type Unknown @@ -11489,7 +11489,7 @@ and POD class 1946 - WP + CD4 exception-specifications vs pointer dereference Unknown @@ -11507,7 +11507,7 @@ and POD class 1949 - DRWP + CD4 “sequenced after” instead of “sequenced before” Unknown @@ -11519,13 +11519,13 @@ and POD class 1951 - DRWP + CD4 Cv-qualification and literal types Unknown 1952 - DRWP + CD4 Constant expressions and library undefined behavior Unknown @@ -11543,13 +11543,13 @@ and POD class 1955 - DR + CD4 #elif with invalid controlling expression Unknown 1956 - DRWP + CD4 Reuse of storage of automatic variables Unknown @@ -11561,13 +11561,13 @@ and POD class 1958 - DRWP + CD4 decltype(auto) with parenthesized initializer Unknown 1959 - DRWP + CD4 Inadvertently inherited copy constructor Clang 3.9 @@ -11578,8 +11578,8 @@ and POD class Unknown - 1961 - ready + 1961 + DR Potentially-concurrent actions within a signal handler Unknown @@ -11591,7 +11591,7 @@ and POD class 1963 - DRWP + CD4 Implementation-defined identifier characters Unknown @@ -11609,13 +11609,13 @@ and POD class 1966 - DRWP + CD4 Colon following enumeration elaborated-type-specifier Unknown 1967 - DRWP + CD4 Temporary lifetime and move-elision Unknown @@ -11639,7 +11639,7 @@ and POD class 1971 - DRWP + CD4 Unclear disambiguation of destructor and operator~ Unknown @@ -11663,7 +11663,7 @@ and POD class 1975 - DRWP + CD4 Permissible declarations for exception-specifications Unknown @@ -11681,7 +11681,7 @@ and POD class 1978 - DRWP + CD4 Redundant description of explicit constructor use Unknown @@ -11699,7 +11699,7 @@ and POD class 1981 - DRWP + CD4 Implicit contextual conversions and explicit Unknown @@ -11741,7 +11741,7 @@ and POD class 1988 - DRWP + CD4 Ambiguity between dependent and non-dependent bases in implicit member access Unknown @@ -11753,19 +11753,19 @@ and POD class 1990 - DRWP + CD4 Ambiguity due to optional decl-specifier-seq Unknown 1991 - DRWP + CD4 Inheriting constructors vs default arguments Clang 3.9 1992 - DR + CD4 new (std::nothrow) int[N] can throw Unknown @@ -11783,7 +11783,7 @@ and POD class 1995 - WP + CD4 exception-specifications and non-type template parameters Unknown @@ -11807,19 +11807,19 @@ and POD class 1999 - DRWP + CD4 Representation of source characters as universal-character-names Unknown 2000 - DRWP + CD4 header-name outside #include directive Unknown 2001 - DR + CD4 non-directive is underspecified Unknown @@ -11837,7 +11837,7 @@ and POD class 2004 - DRWP + CD4 Unions with mutable members in constant expressions Unknown @@ -11849,7 +11849,7 @@ and POD class 2006 - DRWP + CD4 Cv-qualified void types Unknown @@ -11861,7 +11861,7 @@ and POD class 2008 - DR + CD4 Default template-arguments underspecified Unknown @@ -11873,7 +11873,7 @@ and POD class 2010 - WP + CD4 exception-specifications and conversion operators Unknown @@ -11885,7 +11885,7 @@ and POD class 2012 - DR + CD4 Lifetime of references Unknown @@ -11903,19 +11903,19 @@ and POD class 2015 - DRWP + CD4 odr-use of deleted virtual functions Unknown 2016 - DRWP + CD4 Confusing wording in description of conversion function Unknown 2017 - DR + CD4 Flowing off end is not equivalent to no-expression return Unknown @@ -11927,7 +11927,7 @@ and POD class 2019 - DRWP + CD4 Member references omitted from description of storage duration Unknown @@ -11945,7 +11945,7 @@ and POD class 2022 - DRWP + CD4 Copy elision in constant expressions Unknown @@ -11957,7 +11957,7 @@ and POD class 2024 - DRWP + CD4 Dependent types and unexpanded parameter packs Unknown @@ -11969,13 +11969,13 @@ and POD class 2026 - DRWP + CD4 Zero-initialization and constexpr Unknown 2027 - DRWP + CD4 Unclear requirements for multiple alignas specifiers Unknown @@ -11999,19 +11999,19 @@ and POD class 2031 - DRWP + CD4 Missing incompatibility for && Unknown 2032 - DR + CD4 Default template-arguments of variable templates Unknown 2033 - DR + CD4 Redundant restriction on partial specialization argument Unknown @@ -12041,25 +12041,25 @@ and POD class 2038 - DR + CD4 Document C++14 incompatibility of new braced deduction rule Unknown 2039 - DR + CD4 Constant conversions to bool Unknown 2040 - DR + CD4 trailing-return-type no longer ambiguous Unknown 2041 - DR + CD4 Namespace for explicit class template specialization Unknown @@ -12077,7 +12077,7 @@ and POD class 2044 - DR + CD4 decltype(auto) and void Unknown @@ -12095,7 +12095,7 @@ and POD class 2047 - DR + CD4 Coordinating “throws anything” specifications Unknown @@ -12125,7 +12125,7 @@ and POD class 2052 - DRWP + CD4 Template argument deduction vs overloaded operators Unknown @@ -12179,7 +12179,7 @@ and POD class 2061 - DR + CD4 Inline namespace after simplifications Unknown @@ -12191,13 +12191,13 @@ and POD class 2063 - DR + CD4 Type/nontype hiding in class scope Unknown 2064 - DR + CD4 Conflicting specifications for dependent decltype-specifiers Unknown @@ -12209,7 +12209,7 @@ and POD class 2066 - DR + CD4 Does type-dependent imply value-dependent? Unknown @@ -12221,13 +12221,13 @@ and POD class 2068 - DR + CD4 When can/must a defaulted virtual destructor be defined? Unknown 2069 - DR + CD4 Do destructors have names? Unknown @@ -12239,7 +12239,7 @@ and POD class 2071 - DR + CD4 typedef with no declarator Unknown @@ -12263,13 +12263,13 @@ and POD class 2075 - DRWP + CD4 Passing short initializer lists to array reference parameters Unknown 2076 - DRWP + CD4 List-initialization of arguments for constructor parameters Unknown @@ -12287,7 +12287,7 @@ and POD class 2079 - DR + CD4 [[ appearing in a balanced-token-seq Unknown @@ -12305,7 +12305,7 @@ and POD class 2082 - DR + CD4 Referring to parameters in unevaluated operands of default arguments Unknown @@ -12317,13 +12317,13 @@ and POD class 2084 - DR + CD4 NSDMIs and deleted union default constructors Unknown 2085 - DR + CD4 Invalid example of adding special member function via default argument Unknown @@ -12359,7 +12359,7 @@ and POD class 2091 - DRWP + CD4 Deducing reference non-type template arguments Unknown @@ -12371,25 +12371,25 @@ and POD class 2093 - DR + CD4 Qualification conversion for pointer-to-member handler matching Unknown - 2094 - tentatively ready + 2094 + DR Trivial copy/move constructor for class with volatile member - Unknown + Clang 5.0 2095 - DR + CD4 Capturing rvalue references to functions by copy Unknown 2096 - DR + CD4 Constraints on literal unions Unknown @@ -12401,25 +12401,25 @@ and POD class 2098 - DR + CD4 Is uncaught_exceptions() per-thread? Unknown 2099 - DR + CD4 Inferring the bound of an array static data member Unknown - 2100 - tentatively ready + 2100 + DR Value-dependent address of static data member of class template Unknown 2101 - DRWP + CD4 Incorrect description of type- and value-dependence Unknown @@ -12437,7 +12437,7 @@ and POD class 2104 - DR + CD4 Internal-linkage constexpr references and ODR requirements Unknown @@ -12449,13 +12449,13 @@ and POD class 2106 - DR + CD4 Unclear restrictions on use of function-type template arguments Unknown 2107 - DR + CD4 Lifetime of temporaries for default arguments in array copying Unknown @@ -12467,7 +12467,7 @@ and POD class 2109 - DR + CD4 Value dependence underspecified Unknown @@ -12491,7 +12491,7 @@ and POD class 2113 - DR + CD4 Incompete specification of types for declarators Unknown @@ -12533,7 +12533,7 @@ and POD class 2120 - DRWP + CD4 Array as first non-static data member in standard-layout class Unknown @@ -12545,7 +12545,7 @@ and POD class 2122 - DR + CD4 Glvalues of void type Unknown @@ -12557,7 +12557,7 @@ and POD class 2124 - DR + CD4 Signature of constructor template Unknown @@ -12587,13 +12587,13 @@ and POD class 2129 - DR + CD4 Non-object prvalues and constant expressions Unknown 2130 - DR + CD4 Over-aligned types in new-expressions Unknown @@ -12635,7 +12635,7 @@ and POD class 2137 - DRWP + CD4 List-initialization from object of same type Unknown @@ -12653,13 +12653,13 @@ and POD class 2140 - DR + CD4 Lvalue-to-rvalue conversion of std::nullptr_t Unknown 2141 - DR + CD4 Ambiguity in new-expression with elaborated-type-specifier Unknown @@ -12670,8 +12670,8 @@ and POD class Unknown - 2143 - ready + 2143 + DR Value-dependency via injected-class-name Unknown @@ -12683,19 +12683,19 @@ and POD class 2145 - DRWP + CD4 Parenthesized declarator in function definition Unknown 2146 - DR + CD4 Scalar object vs memory location in definition of “unsequenced” Unknown 2147 - DR + CD4 Initializer-list arguments and pack deduction Unknown @@ -12731,31 +12731,31 @@ and POD class 2153 - DR + CD4 pure-specifier in friend declaration Unknown 2154 - DR + CD4 Ambiguity of pure-specifier Unknown - 2155 - ready + 2155 + DR Defining classes and enumerations via using-declarations Unknown 2156 - DR + CD4 Definition of enumeration declared by using-declaration Unknown 2157 - DR + CD4 Further disambiguation of enumeration elaborated-type-specifier Unknown @@ -12791,7 +12791,7 @@ and POD class 2163 - DR + CD4 Labels in constexpr functions Unknown @@ -12815,7 +12815,7 @@ and POD class 2167 - DR + CD4 Non-member references with lifetimes within the current evaluation Unknown @@ -12839,7 +12839,7 @@ and POD class 2171 - DRWP + CD4 Triviality of copy constructor with less-qualified parameter Unknown @@ -12855,21 +12855,21 @@ and POD class Partial specialization with non-deduced contexts Not resolved - + 2174 - drafting + ready Unclear rules for friend definitions in templates - Not resolved + Unknown 2175 - DR + CD4 Ambiguity with attribute in conversion operator declaration Unknown 2176 - DR + CD4 Destroying the returned object when a destructor throws Unknown @@ -12893,7 +12893,7 @@ and POD class 2180 - DR + CD4 Virtual bases in destructors and defaulted assignment operators Yes @@ -12915,11 +12915,11 @@ and POD class Problems in description of potential exceptions Not resolved - - 2184 - review + + 2184 + CD4 Missing C compatibility entry for decrement of bool - Not resolved + Unknown 2185 @@ -12957,11 +12957,11 @@ and POD class Insufficient specification of __has_include Not resolved - + 2191 - open + ready Incorrect result for noexcept(typeid(v)) - Not resolved + Unknown 2192 @@ -12975,11 +12975,11 @@ and POD class numeric_limits<int>::radix and digits Not resolved - + 2194 - open + tentatively ready Impossible case in list initialization - Not resolved + Unknown 2195 @@ -12999,11 +12999,11 @@ and POD class Overload resolution and deleted special member functions Not resolved - + 2198 - open + tentatively ready Linkage of enumerators - Not resolved + Unknown 2199 @@ -13017,11 +13017,11 @@ and POD class Conversions in template argument deduction Not resolved - + 2201 - open + tentatively ready Cv-qualification of array types - Not resolved + Unknown 2202 @@ -13041,17 +13041,17 @@ and POD class Naming delegated constructors Not resolved - + 2205 - open + ready Restrictions on use of alignas - Not resolved + Unknown - + 2206 - open + tentatively ready Composite type of object and function pointers - Not resolved + Unknown 2207 @@ -13095,11 +13095,11 @@ and POD class Forward declaration of partial specializations Not resolved - + 2214 - open + tentatively ready Missing requirement on representation of integer values - Not resolved + Unknown 2215 @@ -13119,11 +13119,11 @@ and POD class constexpr constructors for non-literal types Not resolved - + 2218 - open + ready Ambiguity and namespace aliases - Not resolved + Unknown 2219 @@ -13131,11 +13131,11 @@ and POD class Dynamically-unreachable handlers Not resolved - + 2220 - open + tentatively ready Hiding index variable in range-based for - Not resolved + Unknown 2221 @@ -13155,11 +13155,11 @@ and POD class Multiple alignas specifiers Not resolved - + 2224 - open + tentatively ready Member subobjects and base-class casts - Not resolved + Unknown 2225 @@ -13301,7 +13301,7 @@ and POD class 2248 - open + review Problems with sized delete Not resolved @@ -13319,7 +13319,7 @@ and POD class 2251 - open + review Unreachable enumeration list-initialization Not resolved @@ -13365,11 +13365,11 @@ and POD class Storage deallocation during period of destruction Not resolved - + 2259 - open + tentatively ready Unclear context describing ambiguity - Not resolved + Unknown 2260 @@ -13383,11 +13383,11 @@ and POD class Explicit instantiation of in-class friend definition Not resolved - + 2262 - open + tentatively ready Attributes for asm-definition - Not resolved + Unknown 2263 @@ -13438,11 +13438,47 @@ and POD class Not resolved - 2271 - ready + 2271 + DR Aliasing this Unknown + + 2272 + open + Implicit initialization of aggregate members of reference type + Not resolved + + + 2273 + open + Inheriting constructors vs implicit default constructor + Not resolved + + + 2274 + open + Generic lambda capture vs constexpr if + Not resolved + + + 2275 + open + Type-dependence of function template + Not resolved + + + 2276 + open + Dependent noexcept and function type-dependence + Not resolved + + + 2277 + open + Ambiguity inheriting constructors with default arguments + Not resolved +