Index: cmake/caches/Fuchsia-stage2.cmake =================================================================== --- cmake/caches/Fuchsia-stage2.cmake +++ cmake/caches/Fuchsia-stage2.cmake @@ -1,7 +1,7 @@ # This file sets up a CMakeCache for the second stage of a Fuchsia toolchain # build. -set(LLVM_TARGETS_TO_BUILD X86;AArch64 CACHE STRING "") +set(LLVM_TARGETS_TO_BUILD X86;ARM;AArch64 CACHE STRING "") set(PACKAGE_VENDOR Fuchsia CACHE STRING "") @@ -36,6 +36,7 @@ # Setup toolchain. set(LLVM_INSTALL_TOOLCHAIN_ONLY ON CACHE BOOL "") set(LLVM_TOOLCHAIN_TOOLS + llc llvm-ar llvm-cov llvm-cxxfilt @@ -49,6 +50,7 @@ llvm-readobj llvm-size llvm-symbolizer + opt CACHE STRING "") set(LLVM_DISTRIBUTION_COMPONENTS Index: include/clang/AST/CommentSema.h =================================================================== --- include/clang/AST/CommentSema.h +++ include/clang/AST/CommentSema.h @@ -208,6 +208,10 @@ /// \returns \c true if declaration that this comment is attached to declares /// a function pointer. bool isFunctionPointerVarDecl(); + /// \returns \c true if the declaration that this comment is attached to + /// declares a variable or a field whose type is a function or a block + /// pointer. + bool isFunctionOrBlockPointerVarLikeDecl(); bool isFunctionOrMethodVariadic(); bool isObjCMethodDecl(); bool isObjCPropertyDecl(); Index: include/clang/Basic/Diagnostic.td =================================================================== --- include/clang/Basic/Diagnostic.td +++ include/clang/Basic/Diagnostic.td @@ -12,6 +12,8 @@ // //===----------------------------------------------------------------------===// +// See the Internals Manual, section The Diagnostics Subsystem for an overview. + // Define the diagnostic severities. class Severity { string Name = N; @@ -100,10 +102,20 @@ class Error : Diagnostic, SFINAEFailure { bit ShowInSystemHeader = 1; } +// Warnings default to on (but can be default-off'd with DefaultIgnore). +// This is used for warnings about questionable code; warnings about +// accepted language extensions should use Extension or ExtWarn below instead. class Warning : Diagnostic; +// Remarks can be turned on with -R flags and provide commentary, e.g. on +// optimizer decisions. class Remark : Diagnostic; +// Extensions are warnings about accepted language extensions. +// Extension warnings are default-off but enabled by -pedantic. class Extension : Diagnostic; +// ExtWarns are warnings about accepted language extensions. +// ExtWarn warnings are default-on. class ExtWarn : Diagnostic; +// Notes can provide supplementary information on errors, warnings, and remarks. class Note : Diagnostic; Index: include/clang/Basic/DiagnosticParseKinds.td =================================================================== --- include/clang/Basic/DiagnosticParseKinds.td +++ include/clang/Basic/DiagnosticParseKinds.td @@ -1114,14 +1114,12 @@ } // end of Parse Issue category. let CategoryName = "Modules Issue" in { -def err_expected_module_interface_decl : Error< - "expected module declaration at start of module interface">; def err_unexpected_module_decl : Error< - "module declaration must be the first declaration in the translation unit">; + "module declaration can only appear at the top level">; def err_module_expected_ident : Error< - "expected a module name after module%select{| import}0">; -def err_unexpected_module_kind : Error< - "unexpected module kind %0; expected 'implementation' or 'partition'">; + "expected a module name after '%select{module|import}0'">; +def err_module_implementation_partition : Error< + "module partition must be declared 'export'">; def err_attribute_not_module_attr : Error< "%0 attribute cannot be applied to a module">; def err_attribute_not_import_attr : Error< Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -2260,6 +2260,12 @@ def err_diagnose_if_invalid_diagnostic_type : Error< "invalid diagnostic type for 'diagnose_if'; use \"error\" or \"warning\" " "instead">; +def err_attr_wrong_decl_type : Error< + "attribute does not appertain to declaration">; +def warn_attr_wrong_decl_type : Warning< + "attribute does not appertain to decl">; +def warn_attr_ignored : Warning< + "unknown attribute ignored">; def err_constexpr_body_no_return : Error< "no return statement in constexpr function">; def err_constexpr_return_missing_expr : Error< @@ -8801,9 +8807,11 @@ } let CategoryName = "Modules Issue" in { +def err_module_decl_in_module_map_module : Error< + "'module' declaration found while building module from module map">; def err_module_interface_implementation_mismatch : Error< - "%select{'module'|'module partition'|'module implementation'}0 declaration " - "found while %select{not |not |}0building module interface">; + "missing 'export' specifier in 'module' declaration while " + "building module interface">; def err_current_module_name_mismatch : Error< "module name '%0' specified on command line does not match name of module">; def err_module_redefinition : Error< Index: include/clang/Driver/CC1Options.td =================================================================== --- include/clang/Driver/CC1Options.td +++ include/clang/Driver/CC1Options.td @@ -573,6 +573,8 @@ HelpText<"Weakly link in the blocks runtime">; def fexternc_nounwind : Flag<["-"], "fexternc-nounwind">, HelpText<"Assume all functions with C linkage do not unwind">; +def enable_split_dwarf : Flag<["-"], "enable-split-dwarf">, + HelpText<"Use split dwarf/Fission">; def split_dwarf_file : Separate<["-"], "split-dwarf-file">, HelpText<"File name to use for split dwarf debug info output">; def fno_wchar : Flag<["-"], "fno-wchar">, Index: include/clang/Format/Format.h =================================================================== --- include/clang/Format/Format.h +++ include/clang/Format/Format.h @@ -1512,6 +1512,18 @@ cleanupAroundReplacements(StringRef Code, const tooling::Replacements &Replaces, const FormatStyle &Style); +/// \brief Represents the status of a formatting attempt. +struct FormattingAttemptStatus { + /// \brief A value of ``false`` means that any of the affected ranges were not + /// formatted due to a non-recoverable syntax error. + bool FormatComplete = true; + + /// \brief If ``FormatComplete`` is false, ``Line`` records a one-based + /// original line number at which a syntax error might have occurred. This is + /// based on a best-effort analysis and could be imprecise. + unsigned Line = 0; +}; + /// \brief Reformats the given \p Ranges in \p Code. /// /// Each range is extended on either end to its next bigger logic unit, i.e. @@ -1521,13 +1533,20 @@ /// Returns the ``Replacements`` necessary to make all \p Ranges comply with /// \p Style. /// -/// If ``IncompleteFormat`` is non-null, its value will be set to true if any -/// of the affected ranges were not formatted due to a non-recoverable syntax -/// error. +/// If ``Status`` is non-null, its value will be populated with the status of +/// this formatting attempt. See \c FormattingAttemptStatus. tooling::Replacements reformat(const FormatStyle &Style, StringRef Code, ArrayRef Ranges, StringRef FileName = "", - bool *IncompleteFormat = nullptr); + FormattingAttemptStatus *Status = nullptr); + +/// \brief Same as above, except if ``IncompleteFormat`` is non-null, its value +/// will be set to true if any of the affected ranges were not formatted due to +/// a non-recoverable syntax error. +tooling::Replacements reformat(const FormatStyle &Style, StringRef Code, + ArrayRef Ranges, + StringRef FileName, + bool *IncompleteFormat); /// \brief Clean up any erroneous/redundant code in the given \p Ranges in \p /// Code. Index: include/clang/Frontend/CodeGenOptions.def =================================================================== --- include/clang/Frontend/CodeGenOptions.def +++ include/clang/Frontend/CodeGenOptions.def @@ -199,6 +199,7 @@ CODEGENOPT(DebugExplicitImport, 1, 0) ///< Whether or not debug info should ///< contain explicit imports for ///< anonymous namespaces +CODEGENOPT(EnableSplitDwarf, 1, 0) ///< Whether to enable split DWARF CODEGENOPT(SplitDwarfInlining, 1, 1) ///< Whether to include inlining info in the ///< skeleton CU to allow for symbolication ///< of inline stack frames without .dwo files. Index: include/clang/Index/USRGeneration.h =================================================================== --- include/clang/Index/USRGeneration.h +++ include/clang/Index/USRGeneration.h @@ -30,10 +30,14 @@ bool generateUSRForDecl(const Decl *D, SmallVectorImpl &Buf); /// \brief Generate a USR fragment for an Objective-C class. -void generateUSRForObjCClass(StringRef Cls, raw_ostream &OS); +void generateUSRForObjCClass(StringRef Cls, raw_ostream &OS, + StringRef ExtSymbolDefinedIn = "", + StringRef CategoryContextExtSymbolDefinedIn = ""); /// \brief Generate a USR fragment for an Objective-C class category. -void generateUSRForObjCCategory(StringRef Cls, StringRef Cat, raw_ostream &OS); +void generateUSRForObjCCategory(StringRef Cls, StringRef Cat, raw_ostream &OS, + StringRef ClsExtSymbolDefinedIn = "", + StringRef CatExtSymbolDefinedIn = ""); /// \brief Generate a USR fragment for an Objective-C instance variable. The /// complete USR can be created by concatenating the USR for the @@ -48,7 +52,15 @@ void generateUSRForObjCProperty(StringRef Prop, bool isClassProp, raw_ostream &OS); /// \brief Generate a USR fragment for an Objective-C protocol. -void generateUSRForObjCProtocol(StringRef Prot, raw_ostream &OS); +void generateUSRForObjCProtocol(StringRef Prot, raw_ostream &OS, + StringRef ExtSymbolDefinedIn = ""); + +/// Generate USR fragment for a global (non-nested) enum. +void generateUSRForGlobalEnum(StringRef EnumName, raw_ostream &OS, + StringRef ExtSymbolDefinedIn = ""); + +/// Generate a USR fragment for an enum constant. +void generateUSRForEnumConstant(StringRef EnumConstantName, raw_ostream &OS); /// \brief Generate a USR for a macro, including the USR prefix. /// Index: include/clang/Parse/CMakeLists.txt =================================================================== --- include/clang/Parse/CMakeLists.txt +++ include/clang/Parse/CMakeLists.txt @@ -1,7 +1,3 @@ -clang_tablegen(AttrParserStringSwitches.inc -gen-clang-attr-parser-string-switches - -I ${CMAKE_CURRENT_SOURCE_DIR}/../../ - SOURCE ../Basic/Attr.td - TARGET ClangAttrParserStringSwitches) clang_tablegen(AttrSubMatchRulesParserStringSwitches.inc -gen-clang-attr-subject-match-rules-parser-string-switches Index: include/clang/Sema/AttributeList.h =================================================================== --- include/clang/Sema/AttributeList.h +++ include/clang/Sema/AttributeList.h @@ -23,12 +23,15 @@ #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Allocator.h" +#include "llvm/Support/Registry.h" #include namespace clang { class ASTContext; class IdentifierInfo; class Expr; + class Sema; + class AttributeList; /// \brief Represents information about a change in availability for /// an entity, which is part of the encoding of the 'availability' @@ -83,6 +86,82 @@ typedef llvm::PointerUnion ArgsUnion; typedef llvm::SmallVector ArgsVector; +struct ParsedAttrInfo { + /// Which spelling of the attribute this ParsedAttrInfo corresponds to + unsigned SpellingListIndex; + /// Corresponds to the spelling enum of the corresponding Attr class + unsigned SemanticSpelling; + /// Corresponds to the AttributeList::Kind enum + unsigned AttrKind : 16; + /// Corresponds to the AttributeList::Syntax enum + unsigned Syntax : 3; + /// The number of required arguments of this AttributeList + unsigned NumArgs : 4; + /// The number of optional arguments of this attribute + unsigned OptArgs : 4; + /// True if the parsing does not match the semantic content + unsigned HasCustomParsing : 1; + /// True if this attribute is available for certain targets + unsigned IsTargetSpecific : 1; + /// True if this attribute applies to types + unsigned IsType : 1; + /// True if this attribute applies to statements + unsigned IsStmt : 1; + /// True if this attribute has any spellings that are known to GCC + unsigned IsKnownToGCC : 1; + /// True if the arguments to this attribute should be parsed in an + /// unevaluated context + unsigned IsUnevaluatedArgContext : 1; + /// True if the first argument to the attribute is an identifier + unsigned IsIdentifierArg : 1; + /// True if the first argument to the attribute is a type argument + unsigned IsTypeArg : 1; + /// True if this attribute has arguments that require late parsing + unsigned IsLateParsed : 1; + /// True if supprted by pragma attribute + unsigned IsSupportedByPragmaAttribute : 1; + + ParsedAttrInfo() : \ + SpellingListIndex(0), SemanticSpelling(0), AttrKind(0), Syntax(0), \ + NumArgs(0), OptArgs(0), HasCustomParsing(0), IsTargetSpecific(0), \ + IsType(0), IsStmt(0), IsKnownToGCC(0), IsUnevaluatedArgContext(0), \ + IsIdentifierArg(0), IsTypeArg(0), IsLateParsed(0), \ + IsSupportedByPragmaAttribute(0) {} + + virtual ~ParsedAttrInfo() {} + + /// Check whether this attribute appertains to declaration D, + /// issue a diagnostic if not + virtual bool diagAppertainsToDecl(Sema &S, const AttributeList &Attr, \ + const Decl *D) const { + return true; + } + + /// Check if this attribute is allowed by the currently selected + /// language options, issue a diagnostic if it's not + virtual bool diagLangOpts(Sema &S, const AttributeList &Attr) { + return true; + } + + /// Check whether this attribute is allowed for the current Target + virtual bool existsInTarget(const TargetInfo &Target) { + return true; + } + + /// If this ParsedAttrInfo knows how to apply an attribute to a decl + /// then do so and return true, otherwise return false + virtual bool handleDeclAttribute(Sema &S, Decl *D, \ + const AttributeList &Attr) { + return false; + } + + virtual bool GetPragmaAttributeMatchRules(\ + llvm::SmallVectorImpl> &Rules, \ + const LangOptions &LangOpts) { + return false; + } +}; + /// AttributeList - Represents a syntactic attribute. /// /// For a GNU attribute, there are four forms of this construct: @@ -119,7 +198,7 @@ SourceLocation ScopeLoc; SourceLocation EllipsisLoc; - unsigned AttrKind : 16; + std::unique_ptr Info; /// The number of expression arguments this attribute has. /// The expressions themselves are stored after the object. @@ -248,7 +327,7 @@ HasParsedType(false), HasProcessingCache(false), NextInPosition(nullptr), NextInPool(nullptr) { if (numArgs) memcpy(getArgsBuffer(), args, numArgs * sizeof(ArgsUnion)); - AttrKind = getKind(getName(), getScopeName(), syntaxUsed); + Info = getInfo(getName(), getScopeName(), syntaxUsed); } /// Constructor for availability attributes. @@ -271,7 +350,7 @@ memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion)); new (getAvailabilityData()) AvailabilityData( introduced, deprecated, obsoleted, strict, replacementExpr); - AttrKind = getKind(getName(), getScopeName(), syntaxUsed); + Info = getInfo(getName(), getScopeName(), syntaxUsed); } /// Constructor for objc_bridge_related attributes. @@ -290,7 +369,7 @@ Args[0] = Parm1; Args[1] = Parm2; Args[2] = Parm3; - AttrKind = getKind(getName(), getScopeName(), syntaxUsed); + Info = getInfo(getName(), getScopeName(), syntaxUsed); } /// Constructor for type_tag_for_datatype attribute. @@ -309,7 +388,7 @@ new (&ExtraData.MatchingCType) ParsedType(matchingCType); ExtraData.LayoutCompatible = layoutCompatible; ExtraData.MustBeNull = mustBeNull; - AttrKind = getKind(getName(), getScopeName(), syntaxUsed); + Info = getInfo(getName(), getScopeName(), syntaxUsed); } /// Constructor for attributes with a single type argument. @@ -322,7 +401,7 @@ IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(true), HasProcessingCache(false), NextInPosition(nullptr), NextInPool(nullptr){ new (&getTypeBuffer()) ParsedType(typeArg); - AttrKind = getKind(getName(), getScopeName(), syntaxUsed); + Info = getInfo(getName(), getScopeName(), syntaxUsed); } /// Constructor for microsoft __declspec(property) attribute. @@ -336,7 +415,7 @@ IsTypeTagForDatatype(false), IsProperty(true), HasParsedType(false), HasProcessingCache(false), NextInPosition(nullptr), NextInPool(nullptr) { new (&getPropertyDataBuffer()) PropertyData(getterId, setterId); - AttrKind = getKind(getName(), getScopeName(), syntaxUsed); + Info = getInfo(getName(), getScopeName(), syntaxUsed); } friend class AttributePool; @@ -403,9 +482,10 @@ bool isPackExpansion() const { return EllipsisLoc.isValid(); } SourceLocation getEllipsisLoc() const { return EllipsisLoc; } - Kind getKind() const { return Kind(AttrKind); } - static Kind getKind(const IdentifierInfo *Name, const IdentifierInfo *Scope, - Syntax SyntaxUsed); + const std::unique_ptr &getInfo() const { return Info; } + static std::unique_ptr getInfo(const IdentifierInfo *Name,\ + const IdentifierInfo *ScopeName, Syntax SyntaxUsed); + Kind getKind() const { return Kind(Info->AttrKind); } AttributeList *getNext() const { return NextInPosition; } void setNext(AttributeList *N) { NextInPosition = N; } @@ -938,6 +1018,7 @@ ExpectedNamedDecl, }; +typedef llvm::Registry AttrInfoRegistry; } // end namespace clang #endif Index: include/clang/Sema/CMakeLists.txt =================================================================== --- include/clang/Sema/CMakeLists.txt +++ include/clang/Sema/CMakeLists.txt @@ -8,16 +8,6 @@ SOURCE ../Basic/Attr.td TARGET ClangAttrParsedAttrList) -clang_tablegen(AttrParsedAttrKinds.inc -gen-clang-attr-parsed-attr-kinds - -I ${CMAKE_CURRENT_SOURCE_DIR}/../../ - SOURCE ../Basic/Attr.td - TARGET ClangAttrParsedAttrKinds) - -clang_tablegen(AttrSpellingListIndex.inc -gen-clang-attr-spelling-index - -I ${CMAKE_CURRENT_SOURCE_DIR}/../../ - SOURCE ../Basic/Attr.td - TARGET ClangAttrSpellingListIndex) - clang_tablegen(AttrParsedAttrImpl.inc -gen-clang-attr-parsed-attr-impl -I ${CMAKE_CURRENT_SOURCE_DIR}/../../ SOURCE ../Basic/Attr.td Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -1934,7 +1934,8 @@ /// The parser has processed a module-declaration that begins the definition /// of a module interface or implementation. - DeclGroupPtrTy ActOnModuleDecl(SourceLocation ModuleLoc, ModuleDeclKind MDK, + DeclGroupPtrTy ActOnModuleDecl(SourceLocation StartLoc, + SourceLocation ModuleLoc, ModuleDeclKind MDK, ModuleIdPath Path); /// \brief The parser has processed a module import declaration. Index: lib/AST/Comment.cpp =================================================================== --- lib/AST/Comment.cpp +++ lib/AST/Comment.cpp @@ -280,8 +280,25 @@ case Decl::EnumConstant: case Decl::ObjCIvar: case Decl::ObjCAtDefsField: + case Decl::ObjCProperty: { + const TypeSourceInfo *TSI; + if (const auto *VD = dyn_cast(CommentDecl)) + TSI = VD->getTypeSourceInfo(); + else if (const auto *PD = dyn_cast(CommentDecl)) + TSI = PD->getTypeSourceInfo(); + else + TSI = nullptr; + if (TSI) { + TypeLoc TL = TSI->getTypeLoc().getUnqualifiedLoc(); + FunctionTypeLoc FTL; + if (getFunctionTypeLoc(TL, FTL)) { + ParamVars = FTL.getParams(); + ReturnType = FTL.getReturnLoc().getType(); + } + } Kind = VariableKind; break; + } case Decl::Namespace: Kind = NamespaceKind; break; Index: lib/AST/CommentSema.cpp =================================================================== --- lib/AST/CommentSema.cpp +++ lib/AST/CommentSema.cpp @@ -86,7 +86,7 @@ new (Allocator) ParamCommandComment(LocBegin, LocEnd, CommandID, CommandMarker); - if (!isFunctionDecl()) + if (!isFunctionDecl() && !isFunctionOrBlockPointerVarLikeDecl()) Diag(Command->getLocation(), diag::warn_doc_param_not_attached_to_a_function_decl) << CommandMarker @@ -584,7 +584,7 @@ assert(ThisDeclInfo && "should not call this check on a bare comment"); - if (isFunctionDecl()) { + if (isFunctionDecl() || isFunctionOrBlockPointerVarLikeDecl()) { if (ThisDeclInfo->ReturnType->isVoidType()) { unsigned DiagKind; switch (ThisDeclInfo->CommentDecl->getKind()) { @@ -844,6 +844,30 @@ return false; } +bool Sema::isFunctionOrBlockPointerVarLikeDecl() { + if (!ThisDeclInfo) + return false; + if (!ThisDeclInfo->IsFilled) + inspectThisDecl(); + if (ThisDeclInfo->getKind() != DeclInfo::VariableKind || + !ThisDeclInfo->CurrentDecl) + return false; + QualType QT; + if (const auto *VD = dyn_cast(ThisDeclInfo->CurrentDecl)) + QT = VD->getType(); + else if (const auto *PD = + dyn_cast(ThisDeclInfo->CurrentDecl)) + QT = PD->getType(); + else + return false; + // We would like to warn about the 'returns'/'param' commands for + // variables that don't directly specify the function type, so type aliases + // can be ignored. + if (QT->getAs()) + return false; + return QT->isFunctionPointerType() || QT->isBlockPointerType(); +} + bool Sema::isObjCPropertyDecl() { if (!ThisDeclInfo) return false; Index: lib/AST/Decl.cpp =================================================================== --- lib/AST/Decl.cpp +++ lib/AST/Decl.cpp @@ -2251,6 +2251,14 @@ return Eval->IsICE; } +template +static DeclT *getDefinitionOrSelf(DeclT *D) { + assert(D); + if (auto *Def = D->getDefinition()) + return Def; + return D; +} + VarDecl *VarDecl::getTemplateInstantiationPattern() const { // If it's a variable template specialization, find the template or partial // specialization from which it was instantiated. @@ -2262,7 +2270,7 @@ break; VTD = NewVTD; } - return VTD->getTemplatedDecl()->getDefinition(); + return getDefinitionOrSelf(VTD->getTemplatedDecl()); } if (auto *VTPSD = From.dyn_cast()) { @@ -2271,7 +2279,7 @@ break; VTPSD = NewVTPSD; } - return VTPSD->getDefinition(); + return getDefinitionOrSelf(VTPSD); } } @@ -2280,23 +2288,18 @@ VarDecl *VD = getInstantiatedFromStaticDataMember(); while (auto *NewVD = VD->getInstantiatedFromStaticDataMember()) VD = NewVD; - return VD->getDefinition(); + return getDefinitionOrSelf(VD); } } if (VarTemplateDecl *VarTemplate = getDescribedVarTemplate()) { - while (VarTemplate->getInstantiatedFromMemberTemplate()) { if (VarTemplate->isMemberSpecialization()) break; VarTemplate = VarTemplate->getInstantiatedFromMemberTemplate(); } - assert((!VarTemplate->getTemplatedDecl() || - !isTemplateInstantiation(getTemplateSpecializationKind())) && - "couldn't find pattern for variable instantiation"); - - return VarTemplate->getTemplatedDecl(); + return getDefinitionOrSelf(VarTemplate->getTemplatedDecl()); } return nullptr; } @@ -3198,9 +3201,12 @@ FunctionDecl *FunctionDecl::getTemplateInstantiationPattern() const { // Handle class scope explicit specialization special case. - if (getTemplateSpecializationKind() == TSK_ExplicitSpecialization) - return getClassScopeSpecializationPattern(); - + if (getTemplateSpecializationKind() == TSK_ExplicitSpecialization) { + if (auto *Spec = getClassScopeSpecializationPattern()) + return getDefinitionOrSelf(Spec); + return nullptr; + } + // If this is a generic lambda call operator specialization, its // instantiation pattern is always its primary template's pattern // even if its primary template was instantiated from another @@ -3212,16 +3218,10 @@ if (isGenericLambdaCallOperatorSpecialization( dyn_cast(this))) { - assert(getPrimaryTemplate() && "A generic lambda specialization must be " - "generated from a primary call operator " - "template"); - assert(getPrimaryTemplate()->getTemplatedDecl()->getBody() && - "A generic lambda call operator template must always have a body - " - "even if instantiated from a prototype (i.e. as written) member " - "template"); - return getPrimaryTemplate()->getTemplatedDecl(); + assert(getPrimaryTemplate() && "not a generic lambda call operator?"); + return getDefinitionOrSelf(getPrimaryTemplate()->getTemplatedDecl()); } - + if (FunctionTemplateDecl *Primary = getPrimaryTemplate()) { while (Primary->getInstantiatedFromMemberTemplate()) { // If we have hit a point where the user provided a specialization of @@ -3230,11 +3230,14 @@ break; Primary = Primary->getInstantiatedFromMemberTemplate(); } - - return Primary->getTemplatedDecl(); + + return getDefinitionOrSelf(Primary->getTemplatedDecl()); } - - return getInstantiatedFromMemberFunction(); + + if (auto *MFD = getInstantiatedFromMemberFunction()) + return getDefinitionOrSelf(MFD); + + return nullptr; } FunctionTemplateDecl *FunctionDecl::getPrimaryTemplate() const { @@ -3778,7 +3781,7 @@ EnumDecl *ED = getInstantiatedFromMemberEnum(); while (auto *NewED = ED->getInstantiatedFromMemberEnum()) ED = NewED; - return ED; + return getDefinitionOrSelf(ED); } } Index: lib/AST/DeclCXX.cpp =================================================================== --- lib/AST/DeclCXX.cpp +++ lib/AST/DeclCXX.cpp @@ -1364,6 +1364,13 @@ } const CXXRecordDecl *CXXRecordDecl::getTemplateInstantiationPattern() const { + auto GetDefinitionOrSelf = + [](const CXXRecordDecl *D) -> const CXXRecordDecl * { + if (auto *Def = D->getDefinition()) + return Def; + return D; + }; + // If it's a class template specialization, find the template or partial // specialization from which it was instantiated. if (auto *TD = dyn_cast(this)) { @@ -1374,7 +1381,7 @@ break; CTD = NewCTD; } - return CTD->getTemplatedDecl()->getDefinition(); + return GetDefinitionOrSelf(CTD->getTemplatedDecl()); } if (auto *CTPSD = From.dyn_cast()) { @@ -1383,7 +1390,7 @@ break; CTPSD = NewCTPSD; } - return CTPSD->getDefinition(); + return GetDefinitionOrSelf(CTPSD); } } @@ -1392,7 +1399,7 @@ const CXXRecordDecl *RD = this; while (auto *NewRD = RD->getInstantiatedFromMemberClass()) RD = NewRD; - return RD->getDefinition(); + return GetDefinitionOrSelf(RD); } } Index: lib/CodeGen/BackendUtil.cpp =================================================================== --- lib/CodeGen/BackendUtil.cpp +++ lib/CodeGen/BackendUtil.cpp @@ -369,7 +369,9 @@ // Set FP fusion mode. switch (LangOpts.getDefaultFPContractMode()) { case LangOptions::FPC_Off: - Options.AllowFPOpFusion = llvm::FPOpFusion::Strict; + // Preserve any contraction performed by the front-end. (Strict performs + // splitting of the muladd instrinsic in the backend.) + Options.AllowFPOpFusion = llvm::FPOpFusion::Standard; break; case LangOptions::FPC_On: Options.AllowFPOpFusion = llvm::FPOpFusion::Standard; @@ -405,6 +407,8 @@ Options.EmulatedTLS = CodeGenOpts.EmulatedTLS; Options.DebuggerTuning = CodeGenOpts.getDebuggerTuning(); + if (CodeGenOpts.EnableSplitDwarf) + Options.MCOptions.SplitDwarfFile = CodeGenOpts.SplitDwarfFile; Options.MCOptions.MCRelaxAll = CodeGenOpts.RelaxAll; Options.MCOptions.MCSaveTempLabels = CodeGenOpts.SaveTempLabels; Options.MCOptions.MCUseDwarfDirectory = !CodeGenOpts.NoDwarfDirectoryAsm; Index: lib/CodeGen/CGDebugInfo.cpp =================================================================== --- lib/CodeGen/CGDebugInfo.cpp +++ lib/CodeGen/CGDebugInfo.cpp @@ -528,12 +528,14 @@ // Create new compile unit. // FIXME - Eliminate TheCU. TheCU = DBuilder.createCompileUnit( - LangTag, DBuilder.createFile(remapDIPath(MainFileName), - remapDIPath(getCurrentDirname()), CSKind, - Checksum), + LangTag, + DBuilder.createFile(remapDIPath(MainFileName), + remapDIPath(getCurrentDirname()), CSKind, Checksum), Producer, LO.Optimize, CGM.getCodeGenOpts().DwarfDebugFlags, RuntimeVers, - CGM.getCodeGenOpts().SplitDwarfFile, EmissionKind, 0 /* DWOid */, - CGM.getCodeGenOpts().SplitDwarfInlining, + CGM.getCodeGenOpts().EnableSplitDwarf + ? "" + : CGM.getCodeGenOpts().SplitDwarfFile, + EmissionKind, 0 /* DWOid */, CGM.getCodeGenOpts().SplitDwarfInlining, CGM.getCodeGenOpts().DebugInfoForProfiling); } Index: lib/Driver/ToolChains/Clang.cpp =================================================================== --- lib/Driver/ToolChains/Clang.cpp +++ lib/Driver/ToolChains/Clang.cpp @@ -2778,8 +2778,7 @@ CmdArgs.push_back("-fno-split-dwarf-inlining"); if (DebugInfoKind == codegenoptions::NoDebugInfo) DebugInfoKind = codegenoptions::LimitedDebugInfo; - CmdArgs.push_back("-backend-option"); - CmdArgs.push_back("-split-dwarf=Enable"); + CmdArgs.push_back("-enable-split-dwarf"); } // After we've dealt with all combinations of things that could Index: lib/Driver/ToolChains/Darwin.cpp =================================================================== --- lib/Driver/ToolChains/Darwin.cpp +++ lib/Driver/ToolChains/Darwin.cpp @@ -1035,6 +1035,8 @@ const SanitizerArgs &Sanitize = getSanitizerArgs(); if (Sanitize.needsAsanRt()) AddLinkSanitizerLibArgs(Args, CmdArgs, "asan"); + if (Sanitize.needsLsanRt()) + AddLinkSanitizerLibArgs(Args, CmdArgs, "lsan"); if (Sanitize.needsUbsanRt()) AddLinkSanitizerLibArgs(Args, CmdArgs, "ubsan"); if (Sanitize.needsTsanRt()) @@ -1892,6 +1894,7 @@ const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64; SanitizerMask Res = ToolChain::getSupportedSanitizers(); Res |= SanitizerKind::Address; + Res |= SanitizerKind::Leak; if (isTargetMacOS()) { if (!isMacosxVersionLT(10, 9)) Res |= SanitizerKind::Vptr; Index: lib/Driver/ToolChains/Gnu.cpp =================================================================== --- lib/Driver/ToolChains/Gnu.cpp +++ lib/Driver/ToolChains/Gnu.cpp @@ -1747,7 +1747,9 @@ static const char *const ARMTriples[] = {"arm-linux-gnueabi", "arm-linux-androideabi"}; static const char *const ARMHFTriples[] = {"arm-linux-gnueabihf", - "armv7hl-redhat-linux-gnueabi"}; + "armv7hl-redhat-linux-gnueabi", + "armv6hl-suse-linux-gnueabi", + "armv7hl-suse-linux-gnueabi"}; static const char *const ARMebLibDirs[] = {"/lib"}; static const char *const ARMebTriples[] = {"armeb-linux-gnueabi", "armeb-linux-androideabi"}; Index: lib/Format/Format.cpp =================================================================== --- lib/Format/Format.cpp +++ lib/Format/Format.cpp @@ -908,8 +908,8 @@ class Formatter : public TokenAnalyzer { public: Formatter(const Environment &Env, const FormatStyle &Style, - bool *IncompleteFormat) - : TokenAnalyzer(Env, Style), IncompleteFormat(IncompleteFormat) {} + FormattingAttemptStatus *Status) + : TokenAnalyzer(Env, Style), Status(Status) {} tooling::Replacements analyze(TokenAnnotator &Annotator, @@ -931,7 +931,7 @@ Env.getSourceManager(), Whitespaces, Encoding, BinPackInconclusiveFunctions); UnwrappedLineFormatter(&Indenter, &Whitespaces, Style, Tokens.getKeywords(), - IncompleteFormat) + Env.getSourceManager(), Status) .format(AnnotatedLines); for (const auto &R : Whitespaces.generateReplacements()) if (Result.add(R)) @@ -1013,7 +1013,7 @@ } bool BinPackInconclusiveFunctions; - bool *IncompleteFormat; + FormattingAttemptStatus *Status; }; // This class clean up the erroneous/redundant code around the given ranges in @@ -1830,7 +1830,8 @@ tooling::Replacements reformat(const FormatStyle &Style, StringRef Code, ArrayRef Ranges, - StringRef FileName, bool *IncompleteFormat) { + StringRef FileName, + FormattingAttemptStatus *Status) { FormatStyle Expanded = expandPresets(Style); if (Expanded.DisableFormat) return tooling::Replacements(); @@ -1846,11 +1847,11 @@ auto NewEnv = Environment::CreateVirtualEnvironment( *NewCode, FileName, tooling::calculateRangesAfterReplacements(Fixes, Ranges)); - Formatter Format(*NewEnv, Expanded, IncompleteFormat); + Formatter Format(*NewEnv, Expanded, Status); return Fixes.merge(Format.process()); } } - Formatter Format(*Env, Expanded, IncompleteFormat); + Formatter Format(*Env, Expanded, Status); return Format.process(); }; @@ -1866,7 +1867,7 @@ return reformatAfterApplying(Requoter); } - Formatter Format(*Env, Expanded, IncompleteFormat); + Formatter Format(*Env, Expanded, Status); return Format.process(); } @@ -1879,6 +1880,16 @@ return Clean.process(); } +tooling::Replacements reformat(const FormatStyle &Style, StringRef Code, + ArrayRef Ranges, + StringRef FileName, bool *IncompleteFormat) { + FormattingAttemptStatus Status; + auto Result = reformat(Style, Code, Ranges, FileName, &Status); + if (!Status.FormatComplete) + *IncompleteFormat = true; + return Result; +} + tooling::Replacements fixNamespaceEndComments(const FormatStyle &Style, StringRef Code, ArrayRef Ranges, Index: lib/Format/UnwrappedLineFormatter.h =================================================================== --- lib/Format/UnwrappedLineFormatter.h +++ lib/Format/UnwrappedLineFormatter.h @@ -32,9 +32,11 @@ WhitespaceManager *Whitespaces, const FormatStyle &Style, const AdditionalKeywords &Keywords, - bool *IncompleteFormat) + const SourceManager &SourceMgr, + FormattingAttemptStatus *Status) : Indenter(Indenter), Whitespaces(Whitespaces), Style(Style), - Keywords(Keywords), IncompleteFormat(IncompleteFormat) {} + Keywords(Keywords), SourceMgr(SourceMgr), + Status(Status) {} /// \brief Format the current block and return the penalty. unsigned format(const SmallVectorImpl &Lines, @@ -63,7 +65,8 @@ WhitespaceManager *Whitespaces; const FormatStyle &Style; const AdditionalKeywords &Keywords; - bool *IncompleteFormat; + const SourceManager &SourceMgr; + FormattingAttemptStatus *Status; }; } // end namespace format } // end namespace clang Index: lib/Format/UnwrappedLineFormatter.cpp =================================================================== --- lib/Format/UnwrappedLineFormatter.cpp +++ lib/Format/UnwrappedLineFormatter.cpp @@ -835,8 +835,11 @@ bool ShouldFormat = TheLine.Affected || FixIndentation; // We cannot format this line; if the reason is that the line had a // parsing error, remember that. - if (ShouldFormat && TheLine.Type == LT_Invalid && IncompleteFormat) - *IncompleteFormat = true; + if (ShouldFormat && TheLine.Type == LT_Invalid && Status) { + Status->FormatComplete = false; + Status->Line = + SourceMgr.getSpellingLineNumber(TheLine.First->Tok.getLocation()); + } if (ShouldFormat && TheLine.Type != LT_Invalid) { if (!DryRun) Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -519,6 +519,7 @@ Opts.MacroDebugInfo = Args.hasArg(OPT_debug_info_macro); Opts.WholeProgramVTables = Args.hasArg(OPT_fwhole_program_vtables); Opts.LTOVisibilityPublicStd = Args.hasArg(OPT_flto_visibility_public_std); + Opts.EnableSplitDwarf = Args.hasArg(OPT_enable_split_dwarf); Opts.SplitDwarfFile = Args.getLastArgValue(OPT_split_dwarf_file); Opts.SplitDwarfInlining = !Args.hasArg(OPT_fno_split_dwarf_inlining); Opts.DebugTypeExtRefs = Args.hasArg(OPT_dwarf_ext_refs); Index: lib/Frontend/InitPreprocessor.cpp =================================================================== --- lib/Frontend/InitPreprocessor.cpp +++ lib/Frontend/InitPreprocessor.cpp @@ -882,14 +882,16 @@ // The value written by __atomic_test_and_set. // FIXME: This is target-dependent. Builder.defineMacro("__GCC_ATOMIC_TEST_AND_SET_TRUEVAL", "1"); + } + auto addLockFreeMacros = [&](const llvm::Twine &Prefix) { // Used by libc++ and libstdc++ to implement ATOMIC__LOCK_FREE. unsigned InlineWidthBits = TI.getMaxAtomicInlineWidth(); -#define DEFINE_LOCK_FREE_MACRO(TYPE, Type) \ - Builder.defineMacro("__GCC_ATOMIC_" #TYPE "_LOCK_FREE", \ - getLockFreeValue(TI.get##Type##Width(), \ - TI.get##Type##Align(), \ - InlineWidthBits)); +#define DEFINE_LOCK_FREE_MACRO(TYPE, Type) \ + Builder.defineMacro(Prefix + #TYPE "_LOCK_FREE", \ + getLockFreeValue(TI.get##Type##Width(), \ + TI.get##Type##Align(), \ + InlineWidthBits)); DEFINE_LOCK_FREE_MACRO(BOOL, Bool); DEFINE_LOCK_FREE_MACRO(CHAR, Char); DEFINE_LOCK_FREE_MACRO(CHAR16_T, Char16); @@ -899,12 +901,15 @@ DEFINE_LOCK_FREE_MACRO(INT, Int); DEFINE_LOCK_FREE_MACRO(LONG, Long); DEFINE_LOCK_FREE_MACRO(LLONG, LongLong); - Builder.defineMacro("__GCC_ATOMIC_POINTER_LOCK_FREE", + Builder.defineMacro(Prefix + "POINTER_LOCK_FREE", getLockFreeValue(TI.getPointerWidth(0), TI.getPointerAlign(0), InlineWidthBits)); #undef DEFINE_LOCK_FREE_MACRO - } + }; + addLockFreeMacros("__CLANG_ATOMIC_"); + if (!LangOpts.MSVCCompat) + addLockFreeMacros("__GCC_ATOMIC_"); if (LangOpts.NoInlineDefine) Builder.defineMacro("__NO_INLINE__"); Index: lib/Headers/stdatomic.h =================================================================== --- lib/Headers/stdatomic.h +++ lib/Headers/stdatomic.h @@ -40,16 +40,16 @@ /* 7.17.1 Introduction */ -#define ATOMIC_BOOL_LOCK_FREE __GCC_ATOMIC_BOOL_LOCK_FREE -#define ATOMIC_CHAR_LOCK_FREE __GCC_ATOMIC_CHAR_LOCK_FREE -#define ATOMIC_CHAR16_T_LOCK_FREE __GCC_ATOMIC_CHAR16_T_LOCK_FREE -#define ATOMIC_CHAR32_T_LOCK_FREE __GCC_ATOMIC_CHAR32_T_LOCK_FREE -#define ATOMIC_WCHAR_T_LOCK_FREE __GCC_ATOMIC_WCHAR_T_LOCK_FREE -#define ATOMIC_SHORT_LOCK_FREE __GCC_ATOMIC_SHORT_LOCK_FREE -#define ATOMIC_INT_LOCK_FREE __GCC_ATOMIC_INT_LOCK_FREE -#define ATOMIC_LONG_LOCK_FREE __GCC_ATOMIC_LONG_LOCK_FREE -#define ATOMIC_LLONG_LOCK_FREE __GCC_ATOMIC_LLONG_LOCK_FREE -#define ATOMIC_POINTER_LOCK_FREE __GCC_ATOMIC_POINTER_LOCK_FREE +#define ATOMIC_BOOL_LOCK_FREE __CLANG_ATOMIC_BOOL_LOCK_FREE +#define ATOMIC_CHAR_LOCK_FREE __CLANG_ATOMIC_CHAR_LOCK_FREE +#define ATOMIC_CHAR16_T_LOCK_FREE __CLANG_ATOMIC_CHAR16_T_LOCK_FREE +#define ATOMIC_CHAR32_T_LOCK_FREE __CLANG_ATOMIC_CHAR32_T_LOCK_FREE +#define ATOMIC_WCHAR_T_LOCK_FREE __CLANG_ATOMIC_WCHAR_T_LOCK_FREE +#define ATOMIC_SHORT_LOCK_FREE __CLANG_ATOMIC_SHORT_LOCK_FREE +#define ATOMIC_INT_LOCK_FREE __CLANG_ATOMIC_INT_LOCK_FREE +#define ATOMIC_LONG_LOCK_FREE __CLANG_ATOMIC_LONG_LOCK_FREE +#define ATOMIC_LLONG_LOCK_FREE __CLANG_ATOMIC_LLONG_LOCK_FREE +#define ATOMIC_POINTER_LOCK_FREE __CLANG_ATOMIC_POINTER_LOCK_FREE /* 7.17.2 Initialization */ Index: lib/Index/IndexDecl.cpp =================================================================== --- lib/Index/IndexDecl.cpp +++ lib/Index/IndexDecl.cpp @@ -14,6 +14,13 @@ using namespace clang; using namespace index; +#define TRY_DECL(D,CALL_EXPR) \ + do { \ + if (!IndexCtx.shouldIndex(D)) return true; \ + if (!CALL_EXPR) \ + return false; \ + } while (0) + #define TRY_TO(CALL_EXPR) \ do { \ if (!CALL_EXPR) \ @@ -120,8 +127,7 @@ D->getDeclContext(), 0); } - if (!IndexCtx.handleDecl(D, MethodLoc, Roles, Relations)) - return false; + TRY_DECL(D, IndexCtx.handleDecl(D, MethodLoc, Roles, Relations)); IndexCtx.indexTypeSourceInfo(D->getReturnTypeSourceInfo(), D); bool hasIBActionAndFirst = D->hasAttr(); for (const auto *I : D->parameters()) { @@ -153,8 +159,7 @@ } } - if (!IndexCtx.handleDecl(D, Roles, Relations)) - return false; + TRY_DECL(D, IndexCtx.handleDecl(D, Roles, Relations)); handleDeclarator(D); if (const CXXConstructorDecl *Ctor = dyn_cast(D)) { @@ -189,16 +194,14 @@ } bool VisitVarDecl(const VarDecl *D) { - if (!IndexCtx.handleDecl(D)) - return false; + TRY_DECL(D, IndexCtx.handleDecl(D)); handleDeclarator(D); IndexCtx.indexBody(D->getInit(), D); return true; } bool VisitFieldDecl(const FieldDecl *D) { - if (!IndexCtx.handleDecl(D)) - return false; + TRY_DECL(D, IndexCtx.handleDecl(D)); handleDeclarator(D); if (D->isBitField()) IndexCtx.indexBody(D->getBitWidth(), D); @@ -212,8 +215,7 @@ // handled in VisitObjCPropertyImplDecl return true; } - if (!IndexCtx.handleDecl(D)) - return false; + TRY_DECL(D, IndexCtx.handleDecl(D)); handleDeclarator(D); return true; } @@ -224,17 +226,16 @@ } bool VisitEnumConstantDecl(const EnumConstantDecl *D) { - if (!IndexCtx.handleDecl(D)) - return false; + TRY_DECL(D, IndexCtx.handleDecl(D)); IndexCtx.indexBody(D->getInitExpr(), D); return true; } bool VisitTypedefNameDecl(const TypedefNameDecl *D) { - if (!D->isTransparentTag()) - if (!IndexCtx.handleDecl(D)) - return false; - IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); + if (!D->isTransparentTag()) { + TRY_DECL(D, IndexCtx.handleDecl(D)); + IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); + } return true; } @@ -272,7 +273,7 @@ bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) { if (D->isThisDeclarationADefinition()) { - TRY_TO(IndexCtx.handleDecl(D)); + TRY_DECL(D, IndexCtx.handleDecl(D)); SourceLocation SuperLoc = D->getSuperClassLoc(); if (auto *SuperD = D->getSuperClass()) { bool hasSuperTypedef = false; @@ -303,7 +304,7 @@ bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) { if (D->isThisDeclarationADefinition()) { - TRY_TO(IndexCtx.handleDecl(D)); + TRY_DECL(D, IndexCtx.handleDecl(D)); TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D, /*superLoc=*/SourceLocation())); TRY_TO(IndexCtx.indexDeclContext(D)); @@ -322,8 +323,7 @@ if (Class->isImplicitInterfaceDecl()) IndexCtx.handleDecl(Class); - if (!IndexCtx.handleDecl(D)) - return false; + TRY_DECL(D, IndexCtx.handleDecl(D)); // Visit implicit @synthesize property implementations first as their // location is reported at the name of the @implementation block. This @@ -342,6 +342,8 @@ } bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) { + if (!IndexCtx.shouldIndex(D)) + return true; const ObjCInterfaceDecl *C = D->getClassInterface(); if (!C) return true; @@ -370,8 +372,7 @@ SourceLocation CategoryLoc = D->getCategoryNameLoc(); if (!CategoryLoc.isValid()) CategoryLoc = D->getLocation(); - if (!IndexCtx.handleDecl(D, CategoryLoc)) - return false; + TRY_DECL(D, IndexCtx.handleDecl(D, CategoryLoc)); IndexCtx.indexDeclContext(D); return true; } @@ -393,8 +394,7 @@ if (ObjCMethodDecl *MD = D->getSetterMethodDecl()) if (MD->getLexicalDeclContext() == D->getLexicalDeclContext()) handleObjCMethod(MD, D); - if (!IndexCtx.handleDecl(D)) - return false; + TRY_DECL(D, IndexCtx.handleDecl(D)); if (IBOutletCollectionAttr *attr = D->getAttr()) IndexCtx.indexTypeSourceInfo(attr->getInterfaceLoc(), D, D->getLexicalDeclContext(), false, true); @@ -415,8 +415,7 @@ Loc = Container->getLocation(); Roles |= (SymbolRoleSet)SymbolRole::Implicit; } - if (!IndexCtx.handleDecl(D, Loc, Roles, Relations)) - return false; + TRY_DECL(D, IndexCtx.handleDecl(D, Loc, Roles, Relations)); if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) return true; @@ -450,8 +449,7 @@ } else if (D->getLocation() == IvarLoc) { IvarRoles = (SymbolRoleSet)SymbolRole::Implicit; } - if(!IndexCtx.handleDecl(IvarD, IvarLoc, IvarRoles)) - return false; + TRY_DECL(IvarD, IndexCtx.handleDecl(IvarD, IvarLoc, IvarRoles)); } else { IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), nullptr, D->getDeclContext(), SymbolRoleSet()); @@ -461,8 +459,7 @@ } bool VisitNamespaceDecl(const NamespaceDecl *D) { - if (!IndexCtx.handleDecl(D)) - return false; + TRY_DECL(D, IndexCtx.handleDecl(D)); IndexCtx.indexDeclContext(D); return true; } Index: lib/Index/IndexTypeSourceInfo.cpp =================================================================== --- lib/Index/IndexTypeSourceInfo.cpp +++ lib/Index/IndexTypeSourceInfo.cpp @@ -210,6 +210,8 @@ void IndexingContext::indexTagDecl(const TagDecl *D, ArrayRef Relations) { + if (!shouldIndex(D)) + return; if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalSymbol(D)) return; Index: lib/Index/IndexingContext.h =================================================================== --- lib/Index/IndexingContext.h +++ lib/Index/IndexingContext.h @@ -48,6 +48,8 @@ void setASTContext(ASTContext &ctx) { Ctx = &ctx; } + bool shouldIndex(const Decl *D); + bool shouldSuppressRefs() const { return false; } Index: lib/Index/IndexingContext.cpp =================================================================== --- lib/Index/IndexingContext.cpp +++ lib/Index/IndexingContext.cpp @@ -17,6 +17,17 @@ using namespace clang; using namespace index; +static bool isGeneratedDecl(const Decl *D) { + if (auto *attr = D->getAttr()) { + return attr->getGeneratedDeclaration(); + } + return false; +} + +bool IndexingContext::shouldIndex(const Decl *D) { + return !isGeneratedDecl(D); +} + bool IndexingContext::shouldIndexFunctionLocalSymbols() const { return IndexOpts.IndexFunctionLocals; } Index: lib/Index/USRGeneration.cpp =================================================================== --- lib/Index/USRGeneration.cpp +++ lib/Index/USRGeneration.cpp @@ -46,6 +46,15 @@ return false; } +static StringRef GetExternalSourceContainer(const NamedDecl *D) { + if (!D) + return StringRef(); + if (auto *attr = D->getAttr()) { + return attr->getDefinedIn(); + } + return StringRef(); +} + namespace { class USRGenerator : public ConstDeclVisitor { SmallVectorImpl &Buf; @@ -79,7 +88,8 @@ void VisitNamespaceAliasDecl(const NamespaceAliasDecl *D); void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D); void VisitClassTemplateDecl(const ClassTemplateDecl *D); - void VisitObjCContainerDecl(const ObjCContainerDecl *CD); + void VisitObjCContainerDecl(const ObjCContainerDecl *CD, + const ObjCCategoryDecl *CatD = nullptr); void VisitObjCMethodDecl(const ObjCMethodDecl *MD); void VisitObjCPropertyDecl(const ObjCPropertyDecl *D); void VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D); @@ -116,6 +126,8 @@ return D->getParentFunctionOrMethod() != nullptr; } + void GenExtSymbolContainer(const NamedDecl *D); + /// Generate the string component containing the location of the /// declaration. bool GenLoc(const Decl *D, bool IncludeOffset); @@ -127,13 +139,16 @@ /// itself. /// Generate a USR for an Objective-C class. - void GenObjCClass(StringRef cls) { - generateUSRForObjCClass(cls, Out); + void GenObjCClass(StringRef cls, StringRef ExtSymDefinedIn, + StringRef CategoryContextExtSymbolDefinedIn) { + generateUSRForObjCClass(cls, Out, ExtSymDefinedIn, + CategoryContextExtSymbolDefinedIn); } /// Generate a USR for an Objective-C class category. - void GenObjCCategory(StringRef cls, StringRef cat) { - generateUSRForObjCCategory(cls, cat, Out); + void GenObjCCategory(StringRef cls, StringRef cat, + StringRef clsExt, StringRef catExt) { + generateUSRForObjCCategory(cls, cat, Out, clsExt, catExt); } /// Generate a USR fragment for an Objective-C property. @@ -142,8 +157,8 @@ } /// Generate a USR for an Objective-C protocol. - void GenObjCProtocol(StringRef prot) { - generateUSRForObjCProtocol(prot, Out); + void GenObjCProtocol(StringRef prot, StringRef ext) { + generateUSRForObjCProtocol(prot, Out, ext); } void VisitType(QualType T); @@ -204,7 +219,11 @@ if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D))) return; + const unsigned StartSize = Buf.size(); VisitDeclContext(D->getDeclContext()); + if (Buf.size() == StartSize) + GenExtSymbolContainer(D); + bool IsTemplate = false; if (FunctionTemplateDecl *FunTmpl = D->getDescribedFunctionTemplate()) { IsTemplate = true; @@ -367,7 +386,16 @@ IgnoreResults = true; return; } - Visit(ID); + auto getCategoryContext = [](const ObjCMethodDecl *D) -> + const ObjCCategoryDecl * { + if (auto *CD = dyn_cast(D->getDeclContext())) + return CD; + if (auto *ICD = dyn_cast(D->getDeclContext())) + return ICD->getCategoryDecl(); + return nullptr; + }; + auto *CD = getCategoryContext(D); + VisitObjCContainerDecl(ID, CD); } // Ideally we would use 'GenObjCMethod', but this is such a hot path // for Objective-C code that we don't want to use @@ -376,13 +404,15 @@ << DeclarationName(D->getSelector()); } -void USRGenerator::VisitObjCContainerDecl(const ObjCContainerDecl *D) { +void USRGenerator::VisitObjCContainerDecl(const ObjCContainerDecl *D, + const ObjCCategoryDecl *CatD) { switch (D->getKind()) { default: llvm_unreachable("Invalid ObjC container."); case Decl::ObjCInterface: case Decl::ObjCImplementation: - GenObjCClass(D->getName()); + GenObjCClass(D->getName(), GetExternalSourceContainer(D), + GetExternalSourceContainer(CatD)); break; case Decl::ObjCCategory: { const ObjCCategoryDecl *CD = cast(D); @@ -402,7 +432,9 @@ GenLoc(CD, /*IncludeOffset=*/true); } else - GenObjCCategory(ID->getName(), CD->getName()); + GenObjCCategory(ID->getName(), CD->getName(), + GetExternalSourceContainer(ID), + GetExternalSourceContainer(CD)); break; } @@ -417,12 +449,16 @@ IgnoreResults = true; return; } - GenObjCCategory(ID->getName(), CD->getName()); + GenObjCCategory(ID->getName(), CD->getName(), + GetExternalSourceContainer(ID), + GetExternalSourceContainer(CD)); break; } - case Decl::ObjCProtocol: - GenObjCProtocol(cast(D)->getName()); + case Decl::ObjCProtocol: { + const ObjCProtocolDecl *PD = cast(D); + GenObjCProtocol(PD->getName(), GetExternalSourceContainer(PD)); break; + } } } @@ -452,6 +488,8 @@ ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D))) return; + GenExtSymbolContainer(D); + D = D->getCanonicalDecl(); VisitDeclContext(D->getDeclContext()); @@ -544,6 +582,12 @@ GenLoc(D, /*IncludeOffset=*/true); } +void USRGenerator::GenExtSymbolContainer(const NamedDecl *D) { + StringRef Container = GetExternalSourceContainer(D); + if (!Container.empty()) + Out << "@M@" << Container; +} + bool USRGenerator::GenLoc(const Decl *D, bool IncludeOffset) { if (generatedLoc) return IgnoreResults; @@ -866,12 +910,34 @@ // USR generation functions. //===----------------------------------------------------------------------===// -void clang::index::generateUSRForObjCClass(StringRef Cls, raw_ostream &OS) { +static void combineClassAndCategoryExtContainers(StringRef ClsSymDefinedIn, + StringRef CatSymDefinedIn, + raw_ostream &OS) { + if (ClsSymDefinedIn.empty() && CatSymDefinedIn.empty()) + return; + if (CatSymDefinedIn.empty()) { + OS << "@M@" << ClsSymDefinedIn << '@'; + return; + } + OS << "@CM@" << CatSymDefinedIn << '@'; + if (ClsSymDefinedIn != CatSymDefinedIn) { + OS << ClsSymDefinedIn << '@'; + } +} + +void clang::index::generateUSRForObjCClass(StringRef Cls, raw_ostream &OS, + StringRef ExtSymDefinedIn, + StringRef CategoryContextExtSymbolDefinedIn) { + combineClassAndCategoryExtContainers(ExtSymDefinedIn, + CategoryContextExtSymbolDefinedIn, OS); OS << "objc(cs)" << Cls; } void clang::index::generateUSRForObjCCategory(StringRef Cls, StringRef Cat, - raw_ostream &OS) { + raw_ostream &OS, + StringRef ClsSymDefinedIn, + StringRef CatSymDefinedIn) { + combineClassAndCategoryExtContainers(ClsSymDefinedIn, CatSymDefinedIn, OS); OS << "objc(cy)" << Cls << '@' << Cat; } @@ -890,10 +956,25 @@ OS << (isClassProp ? "(cpy)" : "(py)") << Prop; } -void clang::index::generateUSRForObjCProtocol(StringRef Prot, raw_ostream &OS) { +void clang::index::generateUSRForObjCProtocol(StringRef Prot, raw_ostream &OS, + StringRef ExtSymDefinedIn) { + if (!ExtSymDefinedIn.empty()) + OS << "@M@" << ExtSymDefinedIn << '@'; OS << "objc(pl)" << Prot; } +void clang::index::generateUSRForGlobalEnum(StringRef EnumName, raw_ostream &OS, + StringRef ExtSymDefinedIn) { + if (!ExtSymDefinedIn.empty()) + OS << "@M@" << ExtSymDefinedIn; + OS << "@E@" << EnumName; +} + +void clang::index::generateUSRForEnumConstant(StringRef EnumConstantName, + raw_ostream &OS) { + OS << '@' << EnumConstantName; +} + bool clang::index::generateUSRForDecl(const Decl *D, SmallVectorImpl &Buf) { if (!D) Index: lib/Parse/ParseDecl.cpp =================================================================== --- lib/Parse/ParseDecl.cpp +++ lib/Parse/ParseDecl.cpp @@ -71,16 +71,6 @@ return Actions.ActOnTypeName(getCurScope(), DeclaratorInfo); } -/// isAttributeLateParsed - Return true if the attribute has arguments that -/// require late parsing. -static bool isAttributeLateParsed(const IdentifierInfo &II) { -#define CLANG_ATTR_LATE_PARSED_LIST - return llvm::StringSwitch(II.getName()) -#include "clang/Parse/AttrParserStringSwitches.inc" - .Default(false); -#undef CLANG_ATTR_LATE_PARSED_LIST -} - /// ParseGNUAttributes - Parse a non-empty attributes list. /// /// [GNU] attributes: @@ -161,7 +151,8 @@ } // Handle "parameterized" attributes - if (!LateAttrs || !isAttributeLateParsed(*AttrName)) { + std::unique_ptr Info = AttributeList::getInfo(AttrName, nullptr, AttributeList::AS_GNU); + if (!LateAttrs || !Info->IsLateParsed) { ParseGNUAttributeArgs(AttrName, AttrNameLoc, attrs, endLoc, nullptr, SourceLocation(), AttributeList::AS_GNU, D); continue; @@ -207,34 +198,6 @@ return Name; } -/// \brief Determine whether the given attribute has an identifier argument. -static bool attributeHasIdentifierArg(const IdentifierInfo &II) { -#define CLANG_ATTR_IDENTIFIER_ARG_LIST - return llvm::StringSwitch(normalizeAttrName(II.getName())) -#include "clang/Parse/AttrParserStringSwitches.inc" - .Default(false); -#undef CLANG_ATTR_IDENTIFIER_ARG_LIST -} - -/// \brief Determine whether the given attribute parses a type argument. -static bool attributeIsTypeArgAttr(const IdentifierInfo &II) { -#define CLANG_ATTR_TYPE_ARG_LIST - return llvm::StringSwitch(normalizeAttrName(II.getName())) -#include "clang/Parse/AttrParserStringSwitches.inc" - .Default(false); -#undef CLANG_ATTR_TYPE_ARG_LIST -} - -/// \brief Determine whether the given attribute requires parsing its arguments -/// in an unevaluated context or not. -static bool attributeParsedArgsUnevaluated(const IdentifierInfo &II) { -#define CLANG_ATTR_ARG_CONTEXT_LIST - return llvm::StringSwitch(normalizeAttrName(II.getName())) -#include "clang/Parse/AttrParserStringSwitches.inc" - .Default(false); -#undef CLANG_ATTR_ARG_CONTEXT_LIST -} - IdentifierLoc *Parser::ParseIdentifierLoc() { assert(Tok.is(tok::identifier) && "expected an identifier"); IdentifierLoc *IL = IdentifierLoc::create(Actions.Context, @@ -280,12 +243,14 @@ // Ignore the left paren location for now. ConsumeParen(); + std::unique_ptr Info = \ + AttributeList::getInfo(AttrName, ScopeName, Syntax); + ArgsVector ArgExprs; if (Tok.is(tok::identifier)) { // If this attribute wants an 'identifier' argument, make it so. - bool IsIdentifierArg = attributeHasIdentifierArg(*AttrName); - AttributeList::Kind AttrKind = - AttributeList::getKind(AttrName, ScopeName, Syntax); + bool IsIdentifierArg = Info->IsIdentifierArg; + AttributeList::Kind AttrKind = AttributeList::Kind(Info->AttrKind); // If we don't know how to parse this attribute, but this is the only // token in this argument, assume it's meant to be an identifier. @@ -306,7 +271,7 @@ // Parse the non-empty comma-separated list of expressions. do { - bool Uneval = attributeParsedArgsUnevaluated(*AttrName); + bool Uneval = Info->IsUnevaluatedArgContext; EnterExpressionEvaluationContext Unevaluated( Actions, Uneval ? Sema::ExpressionEvaluationContext::Unevaluated @@ -351,8 +316,11 @@ assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('"); + std::unique_ptr Info = \ + AttributeList::getInfo(AttrName, ScopeName, Syntax); + AttributeList::Kind AttrKind = - AttributeList::getKind(AttrName, ScopeName, Syntax); + AttributeList::Kind(Info->AttrKind); if (AttrKind == AttributeList::AT_Availability) { ParseAvailabilityAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, @@ -370,7 +338,7 @@ ParseTypeTagForDatatypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, ScopeLoc, Syntax); return; - } else if (attributeIsTypeArgAttr(*AttrName)) { + } else if (Info->IsTypeArg) { ParseAttributeWithTypeArg(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, ScopeLoc, Syntax); return; @@ -401,8 +369,9 @@ SourceLocation ScopeLoc, AttributeList::Syntax Syntax) { assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('"); - AttributeList::Kind AttrKind = - AttributeList::getKind(AttrName, ScopeName, Syntax); + std::unique_ptr Info = \ + AttributeList::getInfo(AttrName, ScopeName, Syntax); + AttributeList::Kind AttrKind = AttributeList::Kind(Info->AttrKind); if (AttrKind == AttributeList::AT_ExternalSourceSymbol) { ParseExternalSourceSymbolAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, Index: lib/Parse/ParseDeclCXX.cpp =================================================================== --- lib/Parse/ParseDeclCXX.cpp +++ lib/Parse/ParseDeclCXX.cpp @@ -3797,8 +3797,8 @@ static bool IsBuiltInOrStandardCXX11Attribute(IdentifierInfo *AttrName, IdentifierInfo *ScopeName) { - switch (AttributeList::getKind(AttrName, ScopeName, - AttributeList::AS_CXX11)) { + switch (AttributeList::getInfo(AttrName, ScopeName, + AttributeList::AS_CXX11)->AttrKind) { case AttributeList::AT_CarriesDependency: case AttributeList::AT_Deprecated: case AttributeList::AT_FallThrough: Index: lib/Parse/ParseExpr.cpp =================================================================== --- lib/Parse/ParseExpr.cpp +++ lib/Parse/ParseExpr.cpp @@ -339,7 +339,7 @@ ColonLoc = Tok.getLocation(); } } - + // Code completion for the right-hand side of an assignment expression // goes through a special hook that takes the left-hand side into account. if (Tok.is(tok::code_completion) && NextTokPrec == prec::Assignment) { @@ -347,7 +347,7 @@ cutOffParsing(); return ExprError(); } - + // Parse another leaf here for the RHS of the operator. // ParseCastExpression works here because all RHS expressions in C have it // as a prefix, at least. However, in C++, an assignment-expression could @@ -456,6 +456,7 @@ if (!getLangOpts().CPlusPlus) continue; } + // Ensure potential typos aren't left undiagnosed. if (LHS.isInvalid()) { Actions.CorrectDelayedTyposInExpr(OrigLHS); Index: lib/Parse/ParsePragma.cpp =================================================================== --- lib/Parse/ParsePragma.cpp +++ lib/Parse/ParsePragma.cpp @@ -1299,8 +1299,7 @@ if (Tok.getIdentifierInfo()) { // If we suspect that this is an attribute suggest the use of // '__attribute__'. - if (AttributeList::getKind(Tok.getIdentifierInfo(), /*ScopeName=*/nullptr, - AttributeList::AS_GNU) != + if (AttributeList::Kind() != AttributeList::UnknownAttribute) { SourceLocation InsertStartLoc = Tok.getLocation(); ConsumeToken(); Index: lib/Parse/Parser.cpp =================================================================== --- lib/Parse/Parser.cpp +++ lib/Parse/Parser.cpp @@ -534,23 +534,6 @@ } bool Parser::ParseFirstTopLevelDecl(DeclGroupPtrTy &Result) { - // C++ Modules TS: module-declaration must be the first declaration in the - // file. (There can be no preceding preprocessor directives, but we expect - // the lexer to check that.) - if (Tok.is(tok::kw_module)) { - Result = ParseModuleDecl(); - return false; - } else if (getLangOpts().getCompilingModule() == - LangOptions::CMK_ModuleInterface) { - // FIXME: We avoid providing this diagnostic when generating an object file - // from an existing PCM file. This is not a good way to detect this - // condition; we should provide a mechanism to indicate whether we've - // already parsed a declaration in this translation unit and avoid calling - // ParseFirstTopLevelDecl in that case. - if (Actions.TUKind == TU_Module) - Diag(Tok, diag::err_expected_module_interface_decl); - } - // C11 6.9p1 says translation units must have at least one top-level // declaration. C++ doesn't have this restriction. We also don't want to // complain if we have a precompiled header, although technically if the PCH @@ -583,6 +566,14 @@ Result = ParseModuleImport(SourceLocation()); return false; + case tok::kw_export: + if (NextToken().isNot(tok::kw_module)) + break; + LLVM_FALLTHROUGH; + case tok::kw_module: + Result = ParseModuleDecl(); + return false; + case tok::annot_module_include: Actions.ActOnModuleInclude(Tok.getLocation(), reinterpret_cast( @@ -2049,30 +2040,28 @@ /// Parse a C++ Modules TS module declaration, which appears at the beginning /// of a module interface, module partition, or module implementation file. /// -/// module-declaration: [Modules TS + P0273R0] -/// 'module' module-kind[opt] module-name attribute-specifier-seq[opt] ';' -/// module-kind: -/// 'implementation' -/// 'partition' +/// module-declaration: [Modules TS + P0273R0 + P0629R0] +/// 'export'[opt] 'module' 'partition'[opt] +/// module-name attribute-specifier-seq[opt] ';' /// -/// Note that the module-kind values are context-sensitive keywords. +/// Note that 'partition' is a context-sensitive keyword. Parser::DeclGroupPtrTy Parser::ParseModuleDecl() { - assert(Tok.is(tok::kw_module) && getLangOpts().ModulesTS && - "should not be parsing a module declaration"); + SourceLocation StartLoc = Tok.getLocation(); + + Sema::ModuleDeclKind MDK = TryConsumeToken(tok::kw_export) + ? Sema::ModuleDeclKind::Module + : Sema::ModuleDeclKind::Implementation; + + assert(Tok.is(tok::kw_module) && "not a module declaration"); SourceLocation ModuleLoc = ConsumeToken(); - // Check for a module-kind. - Sema::ModuleDeclKind MDK = Sema::ModuleDeclKind::Module; - if (Tok.is(tok::identifier) && NextToken().is(tok::identifier)) { - if (Tok.getIdentifierInfo()->isStr("implementation")) - MDK = Sema::ModuleDeclKind::Implementation; - else if (Tok.getIdentifierInfo()->isStr("partition")) - MDK = Sema::ModuleDeclKind::Partition; - else { - Diag(Tok, diag::err_unexpected_module_kind) << Tok.getIdentifierInfo(); - SkipUntil(tok::semi); - return nullptr; - } + if (Tok.is(tok::identifier) && NextToken().is(tok::identifier) && + Tok.getIdentifierInfo()->isStr("partition")) { + // If 'partition' is present, this must be a module interface unit. + if (MDK != Sema::ModuleDeclKind::Module) + Diag(Tok.getLocation(), diag::err_module_implementation_partition) + << FixItHint::CreateInsertion(ModuleLoc, "export "); + MDK = Sema::ModuleDeclKind::Partition; ConsumeToken(); } @@ -2080,14 +2069,14 @@ if (ParseModuleName(ModuleLoc, Path, /*IsImport*/false)) return nullptr; + // We don't support any module attributes yet; just parse them and diagnose. ParsedAttributesWithRange Attrs(AttrFactory); MaybeParseCXX11Attributes(Attrs); - // We don't support any module attributes yet. ProhibitCXX11Attributes(Attrs, diag::err_attribute_not_module_attr); ExpectAndConsumeSemi(diag::err_module_expected_semi); - return Actions.ActOnModuleDecl(ModuleLoc, MDK, Path); + return Actions.ActOnModuleDecl(StartLoc, ModuleLoc, MDK, Path); } /// Parse a module import declaration. This is essentially the same for Index: lib/Sema/AttributeList.cpp =================================================================== --- lib/Sema/AttributeList.cpp +++ lib/Sema/AttributeList.cpp @@ -23,6 +23,8 @@ #include "llvm/ADT/SmallString.h" using namespace clang; +LLVM_INSTANTIATE_REGISTRY(AttrInfoRegistry) + IdentifierLoc *IdentifierLoc::create(ASTContext &Ctx, SourceLocation Loc, IdentifierInfo *Ident) { IdentifierLoc *Result = new (Ctx) IdentifierLoc; @@ -107,8 +109,6 @@ } while (pool); } -#include "clang/Sema/AttrParsedAttrKinds.inc" - static StringRef normalizeAttrName(StringRef AttrName, StringRef ScopeName, AttributeList::Syntax SyntaxUsed) { // Normalize the attribute name, __foo__ becomes foo. This is only allowable @@ -122,9 +122,11 @@ return AttrName; } -AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name, - const IdentifierInfo *ScopeName, - Syntax SyntaxUsed) { +#include "clang/Sema/AttrParsedAttrImpl.inc" + +std::unique_ptr AttributeList::getInfo\ + (const IdentifierInfo *Name, const IdentifierInfo *ScopeName, \ + Syntax SyntaxUsed) { StringRef AttrName = Name->getName(); SmallString<64> FullName; @@ -139,76 +141,47 @@ FullName += "::"; FullName += AttrName; - return ::getAttrKind(FullName, SyntaxUsed); -} - -unsigned AttributeList::getAttributeSpellingListIndex() const { - // Both variables will be used in tablegen generated - // attribute spell list index matching code. - StringRef Scope = ScopeName ? ScopeName->getName() : ""; - StringRef Name = normalizeAttrName(AttrName->getName(), Scope, - (AttributeList::Syntax)SyntaxUsed); - -#include "clang/Sema/AttrSpellingListIndex.inc" - -} - -struct ParsedAttrInfo { - unsigned NumArgs : 4; - unsigned OptArgs : 4; - unsigned HasCustomParsing : 1; - unsigned IsTargetSpecific : 1; - unsigned IsType : 1; - unsigned IsStmt : 1; - unsigned IsKnownToGCC : 1; - unsigned IsSupportedByPragmaAttribute : 1; - - virtual bool diagAppertainsToDecl(Sema &S, const AttributeList &Attr,\ - const Decl* D) const { - return true; + // When context-sensitive keyword syntax is used, + // it matches keyword attributes + if (SyntaxUsed == AS_ContextSensitiveKeyword) { + SyntaxUsed = AS_Keyword; } - virtual bool diagLangOpts(Sema &S, const AttributeList &Attr) const { - return true; - } - - virtual bool existsInTarget(const TargetInfo &Target) const { - return true; - } - - virtual unsigned spellingIndexToSemanticSpelling(const AttributeList &Attr)\ - const { - return UINT_MAX; - } - - virtual void getPragmaAttributeMatchRules(\ - llvm::SmallVectorImpl> &Rules,\ - const LangOptions &LangOpts) { + // Search for a ParsedAttrInfo whose name and syntax match + for (AttrInfoRegistry::iterator it = AttrInfoRegistry::begin(), \ + ie = AttrInfoRegistry::end(); it != ie; ++it) { + if (FullName.equals(it->getName())) { + std::unique_ptr P = it->instantiate(); + if (P->Syntax == SyntaxUsed) { + return P; + } + } } -}; -namespace { - #include "clang/Sema/AttrParsedAttrImpl.inc" + // If we failed to find a match then the attribute is unknown + std::unique_ptr ret = llvm::make_unique(); + ret->AttrKind = AttributeList::UnknownAttribute; + return ret; } -static const ParsedAttrInfo &getInfo(const AttributeList &A) { - return *AttrInfoMap[A.getKind()]; +unsigned AttributeList::getAttributeSpellingListIndex() const { + return getInfo()->SpellingListIndex; } unsigned AttributeList::getMinArgs() const { - return getInfo(*this).NumArgs; + return getInfo()->NumArgs; } unsigned AttributeList::getMaxArgs() const { - return getMinArgs() + getInfo(*this).OptArgs; + return getMinArgs() + getInfo()->OptArgs; } bool AttributeList::hasCustomParsing() const { - return getInfo(*this).HasCustomParsing; + return getInfo()->HasCustomParsing; } bool AttributeList::diagnoseAppertainsTo(Sema &S, const Decl *D) const { - return getInfo(*this).diagAppertainsToDecl(S, *this, D); + return getInfo()->diagAppertainsToDecl(S, *this, D); } bool AttributeList::appliesToDecl(const Decl *D, @@ -220,39 +193,39 @@ const LangOptions &LangOpts, SmallVectorImpl> &MatchRules) const { - return getInfo(*this).GetPragmaAttributeMatchRules(MatchRules, LangOpts); + getInfo()->GetPragmaAttributeMatchRules(MatchRules, LangOpts); } bool AttributeList::diagnoseLangOpts(Sema &S) const { - return getInfo(*this).diagLangOpts(S, *this); + return getInfo()->diagLangOpts(S, *this); } bool AttributeList::isTargetSpecificAttr() const { - return getInfo(*this).IsTargetSpecific; + return getInfo()->IsTargetSpecific; } bool AttributeList::isTypeAttr() const { - return getInfo(*this).IsType; + return getInfo()->IsType; } bool AttributeList::isStmtAttr() const { - return getInfo(*this).IsStmt; + return getInfo()->IsStmt; } bool AttributeList::existsInTarget(const TargetInfo &Target) const { - return getInfo(*this).existsInTarget(Target); + return getInfo()->existsInTarget(Target); } bool AttributeList::isKnownToGCC() const { - return getInfo(*this).IsKnownToGCC; + return getInfo()->IsKnownToGCC; } bool AttributeList::isSupportedByPragmaAttribute() const { - return getInfo(*this).IsSupportedByPragmaAttribute; + return getInfo()->IsSupportedByPragmaAttribute; } unsigned AttributeList::getSemanticSpelling() const { - return getInfo(*this).spellingIndexToSemanticSpelling(*this); + return getInfo()->SemanticSpelling; } bool AttributeList::hasVariadicArg() const { @@ -260,5 +233,5 @@ // claim that as being variadic. If we someday get an attribute that // legitimately bumps up against that maximum, we can use another bit to track // whether it's truly variadic or not. - return getInfo(*this).OptArgs == 15; + return getInfo()->OptArgs == 15; } Index: lib/Sema/SemaChecking.cpp =================================================================== --- lib/Sema/SemaChecking.cpp +++ lib/Sema/SemaChecking.cpp @@ -408,7 +408,7 @@ } // Third argument is always an ndrange_t type. - if (Arg2->getType().getAsString() != "ndrange_t") { + if (Arg2->getType().getUnqualifiedType().getAsString() != "ndrange_t") { S.Diag(TheCall->getArg(2)->getLocStart(), diag::err_opencl_enqueue_kernel_expected_type) << "'ndrange_t'"; Index: lib/Sema/SemaDecl.cpp =================================================================== --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -13523,7 +13523,8 @@ // If this is an undefined enum, warn. if (TUK != TUK_Definition && !Invalid) { TagDecl *Def; - if ((getLangOpts().CPlusPlus11 || getLangOpts().ObjC2) && + if (!EnumUnderlyingIsImplicit && + (getLangOpts().CPlusPlus11 || getLangOpts().ObjC2) && cast(New)->isFixed()) { // C++0x: 7.2p2: opaque-enum-declaration. // Conflicts are diagnosed above. Do nothing. @@ -15687,30 +15688,41 @@ } } -Sema::DeclGroupPtrTy Sema::ActOnModuleDecl(SourceLocation ModuleLoc, +Sema::DeclGroupPtrTy Sema::ActOnModuleDecl(SourceLocation StartLoc, + SourceLocation ModuleLoc, ModuleDeclKind MDK, ModuleIdPath Path) { - // 'module implementation' requires that we are not compiling a module of any - // kind. 'module' and 'module partition' require that we are compiling a - // module inteface (not a module map). - auto CMK = getLangOpts().getCompilingModule(); - if (MDK == ModuleDeclKind::Implementation - ? CMK != LangOptions::CMK_None - : CMK != LangOptions::CMK_ModuleInterface) { + // A module implementation unit requires that we are not compiling a module + // of any kind. A module interface unit requires that we are not compiling a + // module map. + switch (getLangOpts().getCompilingModule()) { + case LangOptions::CMK_None: + // It's OK to compile a module interface as a normal translation unit. + break; + + case LangOptions::CMK_ModuleInterface: + if (MDK != ModuleDeclKind::Implementation) + break; + + // We were asked to compile a module interface unit but this is a module + // implementation unit. That indicates the 'export' is missing. Diag(ModuleLoc, diag::err_module_interface_implementation_mismatch) - << (unsigned)MDK; + << FixItHint::CreateInsertion(ModuleLoc, "export "); + break; + + case LangOptions::CMK_ModuleMap: + Diag(ModuleLoc, diag::err_module_decl_in_module_map_module); return nullptr; } // FIXME: Create a ModuleDecl and return it. // FIXME: Most of this work should be done by the preprocessor rather than - // here, in case we look ahead across something where the current - // module matters (eg a #include). + // here, in order to support macro import. - // The dots in a module name in the Modules TS are a lie. Unlike Clang's - // hierarchical module map modules, the dots here are just another character - // that can appear in a module name. Flatten down to the actual module name. + // Flatten the dots in a module name. Unlike Clang's hierarchical module map + // modules, the dots here are just another character that can appear in a + // module name. std::string ModuleName; for (auto &Piece : Path) { if (!ModuleName.empty()) @@ -15735,8 +15747,8 @@ case ModuleDeclKind::Module: { // FIXME: Check we're not in a submodule. - // We can't have imported a definition of this module or parsed a module - // map defining it already. + // We can't have parsed or imported a definition of this module or parsed a + // module map defining it already. if (auto *M = Map.findModule(ModuleName)) { Diag(Path[0].second, diag::err_module_redefinition) << ModuleName; if (M->DefinitionLoc.isValid()) Index: lib/Sema/SemaDeclAttr.cpp =================================================================== --- lib/Sema/SemaDeclAttr.cpp +++ lib/Sema/SemaDeclAttr.cpp @@ -5858,6 +5858,9 @@ if (handleCommonAttributeFeatures(S, scope, D, Attr)) return; + if (Attr.getInfo()->handleDeclAttribute(S, D, Attr)) + return; + switch (Attr.getKind()) { default: if (!Attr.isStmtAttr()) { Index: lib/Sema/SemaLookup.cpp =================================================================== --- lib/Sema/SemaLookup.cpp +++ lib/Sema/SemaLookup.cpp @@ -1326,12 +1326,6 @@ return !R.empty(); } -/// \brief Find the declaration that a class temploid member specialization was -/// instantiated from, or the member itself if it is an explicit specialization. -static Decl *getInstantiatedFrom(Decl *D, MemberSpecializationInfo *MSInfo) { - return MSInfo->isExplicitSpecialization() ? D : MSInfo->getInstantiatedFrom(); -} - Module *Sema::getOwningModule(Decl *Entity) { // If it's imported, grab its owning module. Module *M = Entity->getImportedOwningModule(); @@ -1413,12 +1407,11 @@ if (CXXRecordDecl *Pattern = RD->getTemplateInstantiationPattern()) Entity = Pattern; } else if (EnumDecl *ED = dyn_cast(Entity)) { - if (MemberSpecializationInfo *MSInfo = ED->getMemberSpecializationInfo()) - Entity = getInstantiatedFrom(ED, MSInfo); + if (auto *Pattern = ED->getTemplateInstantiationPattern()) + Entity = Pattern; } else if (VarDecl *VD = dyn_cast(Entity)) { - // FIXME: Map from variable template specializations back to the template. - if (MemberSpecializationInfo *MSInfo = VD->getMemberSpecializationInfo()) - Entity = getInstantiatedFrom(VD, MSInfo); + if (VarDecl *Pattern = VD->getTemplateInstantiationPattern()) + Entity = Pattern; } // Walk up to the containing context. That might also have been instantiated Index: lib/Sema/TreeTransform.h =================================================================== --- lib/Sema/TreeTransform.h +++ lib/Sema/TreeTransform.h @@ -2220,6 +2220,9 @@ Base = BaseResult.get(); QualType BaseType = Base->getType(); + if (isArrow && !BaseType->isPointerType()) + return ExprError(); + // FIXME: this involves duplicating earlier analysis in a lot of // cases; we should avoid this when possible. LookupResult R(getSema(), MemberNameInfo, Sema::LookupMemberName); Index: lib/StaticAnalyzer/Core/ExprEngine.cpp =================================================================== --- lib/StaticAnalyzer/Core/ExprEngine.cpp +++ lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -1904,8 +1904,8 @@ // Evaluate the LHS of the case value. llvm::APSInt V1 = Case->getLHS()->EvaluateKnownConstInt(getContext()); - assert(V1.getBitWidth() == getContext().getTypeSize(CondE->getType())); - + assert(V1.getBitWidth() == getContext().getIntWidth(CondE->getType())); + // Get the RHS of the case, if it exists. llvm::APSInt V2; if (const Expr *E = Case->getRHS()) Index: test/Analysis/enum.cpp =================================================================== --- test/Analysis/enum.cpp +++ test/Analysis/enum.cpp @@ -24,3 +24,16 @@ clang_analyzer_eval(j == 0); // expected-warning{{FALSE}} } } + +enum class EnumBool : bool { + F = false, + T = true +}; + +bool testNoCrashOnSwitchEnumBool(EnumBool E) { + switch (E) { + case EnumBool::F: + return false; + } + return true; +} Index: test/CXX/modules-ts/basic/basic.link/module-declaration.cpp =================================================================== --- /dev/null +++ test/CXX/modules-ts/basic/basic.link/module-declaration.cpp @@ -0,0 +1,55 @@ +// Tests for module-declaration syntax. +// +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: echo 'export module x; int a, b;' > %t/x.cppm +// RUN: echo 'export module x.y; int c;' > %t/x.y.cppm +// +// RUN: %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %t/x.cppm -o %t/x.pcm +// RUN: %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface -fmodule-file=%t/x.pcm %t/x.y.cppm -o %t/x.y.pcm +// +// Module implementation for unknown and known module. (The former is ill-formed.) +// FIXME: TEST=1 should fail because we don't have an interface for module z. +// RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \ +// RUN: -DTEST=1 -DEXPORT= -DPARTITION= -DMODULE_NAME=z +// RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \ +// RUN: -DTEST=2 -DEXPORT= -DPARTITION= -DMODULE_NAME=x +// +// Module interface for unknown and known module. (The latter is ill-formed due to +// redefinition.) +// RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \ +// RUN: -DTEST=3 -DEXPORT=export -DPARTITION= -DMODULE_NAME=z +// RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \ +// RUN: -DTEST=4 -DEXPORT=export -DPARTITION= -DMODULE_NAME=x +// +// Defining a module partition. +// RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \ +// RUN: -DTEST=5 -DEXPORT=export -DPARTITION=partition -DMODULE_NAME=z +// RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \ +// RUN: -DTEST=6 -DEXPORT= -DPARTITION=partition -DMODULE_NAME=z +// +// Miscellaneous syntax. +// RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \ +// RUN: -DTEST=7 -DEXPORT= -DPARTITION=elderberry -DMODULE_NAME=z +// RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \ +// RUN: -DTEST=8 -DEXPORT= -DPARTITION= -DMODULE_NAME='z [[]]' +// RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \ +// RUN: -DTEST=9 -DEXPORT= -DPARTITION= -DMODULE_NAME='z [[fancy]]' +// RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \ +// RUN: -DTEST=10 -DEXPORT= -DPARTITION= -DMODULE_NAME='z [[maybe_unused]]' + +EXPORT module PARTITION MODULE_NAME; +#if TEST == 4 +// expected-error@-2 {{redefinition of module 'x'}} +// expected-note-re@module-declaration.cpp:* {{loaded from '{{.*}}/x.pcm'}} +#elif TEST == 6 +// expected-error@-5 {{module partition must be declared 'export'}} +#elif TEST == 7 +// expected-error@-7 {{expected ';'}} expected-error@-7 {{requires a type specifier}} +#elif TEST == 9 +// expected-warning@-9 {{unknown attribute 'fancy' ignored}} +#elif TEST == 10 +// expected-error-re@-11 {{'maybe_unused' attribute cannot be applied to a module{{$}}}} +#else +// expected-no-diagnostics +#endif Index: test/CXX/modules-ts/codegen-basics.cppm =================================================================== --- test/CXX/modules-ts/codegen-basics.cppm +++ test/CXX/modules-ts/codegen-basics.cppm @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -fmodules-ts -std=c++1z -triple=x86_64-linux-gnu -fmodules-codegen -emit-module-interface %s -o %t.pcm // RUN: %clang_cc1 -fmodules-ts -std=c++1z -triple=x86_64-linux-gnu %t.pcm -emit-llvm -o - | FileCheck %s -module FooBar; +export module FooBar; export { // CHECK-LABEL: define i32 @_Z1fv( Index: test/CXX/modules-ts/dcl.dcl/dcl.module/dcl.module.import/p1.cpp =================================================================== --- /dev/null +++ test/CXX/modules-ts/dcl.dcl/dcl.module/dcl.module.import/p1.cpp @@ -0,0 +1,41 @@ +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: echo 'export module x; int a, b;' > %t/x.cppm +// RUN: echo 'export module x.y; int c;' > %t/x.y.cppm +// +// RUN: %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %t/x.cppm -o %t/x.pcm +// RUN: %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface -fmodule-file=%t/x.pcm %t/x.y.cppm -o %t/x.y.pcm +// +// RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \ +// RUN: -DMODULE_NAME=z +// RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \ +// RUN: -DMODULE_X -DMODULE_NAME=x + +module MODULE_NAME; + +int use_1 = a; +#if !MODULE_X +// expected-error@-2 {{declaration of 'a' must be imported from module 'x' before it is required}} +// expected-note@x.cppm:1 {{here}} +#endif + +import x; + +int use_2 = b; // ok + +// There is no relation between module x and module x.y. +int use_3 = c; // expected-error {{declaration of 'c' must be imported from module 'x.y'}} + // expected-note@x.y.cppm:1 {{here}} + +import x [[]]; +import x [[foo]]; // expected-warning {{unknown attribute 'foo' ignored}} +import x [[noreturn]]; // expected-error {{'noreturn' attribute cannot be applied to a module import}} +import x [[blarg::noreturn]]; // expected-warning {{unknown attribute 'noreturn' ignored}} + +import x.y; +import x.; // expected-error {{expected a module name after 'import'}} +import .x; // expected-error {{expected a module name after 'import'}} + +int use_4 = c; // ok + +import blarg; // expected-error {{module 'blarg' not found}} Index: test/CodeGen/fp-contract-on-asm.c =================================================================== --- /dev/null +++ test/CodeGen/fp-contract-on-asm.c @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -O3 -triple=aarch64-apple-ios -S -o - %s | FileCheck %s +// REQUIRES: aarch64-registered-target + +float fma_test1(float a, float b, float c) { +#pragma STDC FP_CONTRACT ON +// CHECK-LABEL: fma_test1: +// CHECK: fmadd + float x = a * b + c; + return x; +} + +float fma_test2(float a, float b, float c) { +// CHECK-LABEL: fma_test2: +// CHECK: fmul +// CHECK: fadd + float x = a * b + c; + return x; +} Index: test/CodeGen/split-debug-filename.c =================================================================== --- test/CodeGen/split-debug-filename.c +++ test/CodeGen/split-debug-filename.c @@ -1,7 +1,12 @@ // RUN: %clang_cc1 -debug-info-kind=limited -split-dwarf-file foo.dwo -S -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -debug-info-kind=limited -enable-split-dwarf -split-dwarf-file foo.dwo -S -emit-llvm -o - %s | FileCheck --check-prefix=VANILLA %s int main (void) { return 0; } // Testing to ensure that the dwo name gets output into the compile unit. // CHECK: !DICompileUnit({{.*}}, splitDebugFilename: "foo.dwo" + +// Testing to ensure that the dwo name is not output into the compile unit if +// it's for vanilla split-dwarf rather than split-dwarf for implicit modules. +// VANILLA-NOT: splitDebugFilename Index: test/Driver/avr-mmcu.c =================================================================== --- test/Driver/avr-mmcu.c +++ test/Driver/avr-mmcu.c @@ -1,5 +1,5 @@ // A test for the propagation of the -mmcu option to -cc1 and -cc1as -// RUN: %clang -### -target avr -mmcu=atmega328p -save-temps %s 2>&1 | FileCheck %s +// RUN: %clang -### -target avr -no-canonical-prefixes -mmcu=atmega328p -save-temps %s 2>&1 | FileCheck %s // CHECK: clang{{.*}} "-cc1" {{.*}} "-target-cpu" "atmega328p" // CHECK: clang{{.*}} "-cc1as" {{.*}} "-target-cpu" "atmega328p" Index: test/Driver/fsanitize.c =================================================================== --- test/Driver/fsanitize.c +++ test/Driver/fsanitize.c @@ -358,6 +358,27 @@ // RUN: %clang -target i386-pc-openbsd -fsanitize=address %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-OPENBSD // CHECK-ASAN-OPENBSD: unsupported option '-fsanitize=address' for target 'i386-pc-openbsd' +// RUN: %clang -target x86_64-apple-darwin -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-X86-64-DARWIN +// CHECK-LSAN-X86-64-DARWIN-NOT: unsupported option + +// RUN: %clang -target x86_64-apple-iossimulator -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-X86-64-IOSSIMULATOR +// CHECK-LSAN-X86-64-IOSSIMULATOR-NOT: unsupported option + +// RUN: %clang -target x86_64-apple-tvossimulator -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-X86-64-TVOSSIMULATOR +// CHECK-LSAN-X86-64-TVOSSIMULATOR-NOT: unsupported option + +// RUN: %clang -target i386-apple-darwin -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-I386-DARWIN +// CHECK-LSAN-I386-DARWIN-NOT: unsupported option + +// RUN: %clang -target arm-apple-ios -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-ARM-IOS +// CHECK-LSAN-ARM-IOS-NOT: unsupported option + +// RUN: %clang -target i386-apple-iossimulator -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-I386-IOSSIMULATOR +// CHECK-LSAN-I386-IOSSIMULATOR-NOT: unsupported option + +// RUN: %clang -target i386-apple-tvossimulator -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-I386-TVOSSIMULATOR +// CHECK-LSAN-I386-TVOSSIMULATOR-NOT: unsupported option + // RUN: %clang -target i686-linux-gnu -fsanitize=efficiency-cache-frag %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ESAN-X86 // RUN: %clang -target i686-linux-gnu -fsanitize=efficiency-working-set %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ESAN-X86 // CHECK-ESAN-X86: error: unsupported option '-fsanitize=efficiency-{{.*}}' for target 'i686--linux-gnu' Index: test/Driver/linux-ld.c =================================================================== --- test/Driver/linux-ld.c +++ test/Driver/linux-ld.c @@ -638,6 +638,46 @@ // CHECK-OPENSUSE-42-2-AARCH64: "{{.*}}/usr/lib64/gcc/aarch64-suse-linux/4.8{{/|\\\\}}crtend.o" // CHECK-OPENSUSE-42-2-AARCH64: "{{.*}}/usr/lib64/gcc/aarch64-suse-linux/4.8/../../../../lib64{{/|\\\\}}crtn.o" // +// Check openSUSE Tumbleweed on armv6hl +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: --target=armv6hl-suse-linux-gnueabi \ +// RUN: --gcc-toolchain="" \ +// RUN: --sysroot=%S/Inputs/opensuse_tumbleweed_armv6hl_tree \ +// RUN: | FileCheck --check-prefix=CHECK-OPENSUSE-TW-ARMV6HL %s +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: --target=armv6hl-suse-linux-gnueabi \ +// RUN: --gcc-toolchain="" \ +// RUN: --sysroot=%S/Inputs/opensuse_tumbleweed_armv6hl_tree \ +// RUN: | FileCheck --check-prefix=CHECK-OPENSUSE-TW-ARMV6HL %s +// CHECK-OPENSUSE-TW-ARMV6HL: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" +// CHECK-OPENSUSE-TW-ARMV6HL: "{{.*}}/usr/lib/gcc/armv6hl-suse-linux-gnueabi/5/../../../../lib{{/|\\\\}}crt1.o" +// CHECK-OPENSUSE-TW-ARMV6HL: "{{.*}}/usr/lib/gcc/armv6hl-suse-linux-gnueabi/5/../../../../lib{{/|\\\\}}crti.o" +// CHECK-OPENSUSE-TW-ARMV6HL: "{{.*}}/usr/lib/gcc/armv6hl-suse-linux-gnueabi/5{{/|\\\\}}crtbegin.o" +// CHECK-OPENSUSE-TW-ARMV6HL: "-L[[SYSROOT]]/usr/lib/gcc/armv6hl-suse-linux-gnueabi/5" +// CHECK-OPENSUSE-TW-ARMV6HL: "-L[[SYSROOT]]/usr/lib/gcc/armv6hl-suse-linux-gnueabi/5/../../../../lib" +// CHECK-OPENSUSE-TW-ARMV6HL: "{{.*}}/usr/lib/gcc/armv6hl-suse-linux-gnueabi/5{{/|\\\\}}crtend.o" +// CHECK-OPENSUSE-TW-ARMV6HL: "{{.*}}/usr/lib/gcc/armv6hl-suse-linux-gnueabi/5/../../../../lib{{/|\\\\}}crtn.o" +// +// Check openSUSE Tumbleweed on armv7hl +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: --target=armv7hl-suse-linux-gnueabi \ +// RUN: --gcc-toolchain="" \ +// RUN: --sysroot=%S/Inputs/opensuse_tumbleweed_armv7hl_tree \ +// RUN: | FileCheck --check-prefix=CHECK-OPENSUSE-TW-ARMV7HL %s +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: --target=armv7hl-suse-linux-gnueabi \ +// RUN: --gcc-toolchain="" \ +// RUN: --sysroot=%S/Inputs/opensuse_tumbleweed_armv7hl_tree \ +// RUN: | FileCheck --check-prefix=CHECK-OPENSUSE-TW-ARMV7HL %s +// CHECK-OPENSUSE-TW-ARMV7HL: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" +// CHECK-OPENSUSE-TW-ARMV7HL: "{{.*}}/usr/lib/gcc/armv7hl-suse-linux-gnueabi/5/../../../../lib{{/|\\\\}}crt1.o" +// CHECK-OPENSUSE-TW-ARMV7HL: "{{.*}}/usr/lib/gcc/armv7hl-suse-linux-gnueabi/5/../../../../lib{{/|\\\\}}crti.o" +// CHECK-OPENSUSE-TW-ARMV7HL: "{{.*}}/usr/lib/gcc/armv7hl-suse-linux-gnueabi/5{{/|\\\\}}crtbegin.o" +// CHECK-OPENSUSE-TW-ARMV7HL: "-L[[SYSROOT]]/usr/lib/gcc/armv7hl-suse-linux-gnueabi/5" +// CHECK-OPENSUSE-TW-ARMV7HL: "-L[[SYSROOT]]/usr/lib/gcc/armv7hl-suse-linux-gnueabi/5/../../../../lib" +// CHECK-OPENSUSE-TW-ARMV7HL: "{{.*}}/usr/lib/gcc/armv7hl-suse-linux-gnueabi/5{{/|\\\\}}crtend.o" +// CHECK-OPENSUSE-TW-ARMV7HL: "{{.*}}/usr/lib/gcc/armv7hl-suse-linux-gnueabi/5/../../../../lib{{/|\\\\}}crtn.o" +// // Check dynamic-linker for different archs // RUN: %clang %s -### -o %t.o 2>&1 \ // RUN: --target=arm-linux-gnueabi \ Index: test/Driver/modules-ts.cpp =================================================================== --- test/Driver/modules-ts.cpp +++ test/Driver/modules-ts.cpp @@ -1,6 +1,6 @@ // Check compiling a module interface to a .pcm file. // -// RUN: %clang -fmodules-ts -x c++-module --precompile %s -Dimplementation= -o %t.pcm -v 2>&1 | FileCheck %s --check-prefix=CHECK-PRECOMPILE +// RUN: %clang -fmodules-ts -x c++-module --precompile %s -o %t.pcm -v 2>&1 | FileCheck %s --check-prefix=CHECK-PRECOMPILE // // CHECK-PRECOMPILE: -cc1 {{.*}} -emit-module-interface // CHECK-PRECOMPILE-SAME: -o {{.*}}.pcm @@ -18,7 +18,7 @@ // Check use of a .pcm file in another compilation. // -// RUN: %clang -fmodules-ts -fmodule-file=%t.pcm %s -c -o %t.o -v 2>&1 | FileCheck %s --check-prefix=CHECK-USE +// RUN: %clang -fmodules-ts -fmodule-file=%t.pcm -Dexport= %s -c -o %t.o -v 2>&1 | FileCheck %s --check-prefix=CHECK-USE // // CHECK-USE: -cc1 // CHECK-USE-SAME: -emit-obj @@ -28,11 +28,11 @@ // Check combining precompile and compile steps works. // -// RUN: %clang -fmodules-ts -x c++-module %s -Dimplementation= -c -o %t.pcm.o -v 2>&1 | FileCheck %s --check-prefix=CHECK-PRECOMPILE --check-prefix=CHECK-COMPILE +// RUN: %clang -fmodules-ts -x c++-module %s -c -o %t.pcm.o -v 2>&1 | FileCheck %s --check-prefix=CHECK-PRECOMPILE --check-prefix=CHECK-COMPILE // Check that .cppm is treated as a module implicitly. // RUN: cp %s %t.cppm -// RUN: %clang -fmodules-ts --precompile %t.cppm -Dimplementation= -o %t.pcm -v 2>&1 | FileCheck %s --check-prefix=CHECK-PRECOMPILE +// RUN: %clang -fmodules-ts --precompile %t.cppm -o %t.pcm -v 2>&1 | FileCheck %s --check-prefix=CHECK-PRECOMPILE -// Note, we use -Dimplementation= to make this a valid module interface unit when building the interface. -module implementation foo; +// Note, we use -Dexport= to make this a module implementation unit when building the implementation. +export module foo; Index: test/Driver/sanitizer-ld.c =================================================================== --- test/Driver/sanitizer-ld.c +++ test/Driver/sanitizer-ld.c @@ -409,6 +409,15 @@ // CHECK-ASAN-DARWIN106-CXX: libclang_rt.asan_osx_dynamic.dylib // CHECK-ASAN-DARWIN106-CXX-NOT: -lc++abi +// RUN: %clangxx -fsanitize=leak %s -### -o %t.o 2>&1 \ +// RUN: -mmacosx-version-min=10.6 \ +// RUN: -target x86_64-apple-darwin13.4.0 -fuse-ld=ld -stdlib=platform \ +// RUN: --sysroot=%S/Inputs/basic_linux_tree \ +// RUN: | FileCheck --check-prefix=CHECK-LSAN-DARWIN106-CXX %s +// CHECK-LSAN-DARWIN106-CXX: "{{.*}}ld{{(.exe)?}}" +// CHECK-LSAN-DARWIN106-CXX: libclang_rt.lsan_osx_dynamic.dylib +// CHECK-LSAN-DARWIN106-CXX-NOT: -lc++abi + // RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ // RUN: -target x86_64-unknown-linux -fuse-ld=ld -fsanitize=safe-stack \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ Index: test/Driver/split-debug.c =================================================================== --- test/Driver/split-debug.c +++ test/Driver/split-debug.c @@ -36,53 +36,53 @@ // RUN: %clang -target x86_64-unknown-linux-gnu -gsplit-dwarf -gmlt -fno-split-dwarf-inlining -S -### %s 2> %t // RUN: FileCheck -check-prefix=CHECK-GMLT-WITH-SPLIT < %t %s // -// CHECK-GMLT-WITH-SPLIT: "-split-dwarf=Enable" +// CHECK-GMLT-WITH-SPLIT: "-enable-split-dwarf" // CHECK-GMLT-WITH-SPLIT: "-debug-info-kind=line-tables-only" // CHECK-GMLT-WITH-SPLIT: "-split-dwarf-file" // RUN: %clang -target x86_64-unknown-linux-gnu -gmlt -gsplit-dwarf -fno-split-dwarf-inlining -S -### %s 2> %t // RUN: FileCheck -check-prefix=CHECK-SPLIT-WITH-GMLT < %t %s // -// CHECK-SPLIT-WITH-GMLT: "-split-dwarf=Enable" +// CHECK-SPLIT-WITH-GMLT: "-enable-split-dwarf" // CHECK-SPLIT-WITH-GMLT: "-debug-info-kind=line-tables-only" // CHECK-SPLIT-WITH-GMLT: "-split-dwarf-file" // RUN: %clang -target x86_64-unknown-linux-gnu -gsplit-dwarf -fno-split-dwarf-inlining -S -### %s 2> %t // RUN: FileCheck -check-prefix=CHECK-SPLIT-WITH-NOINL < %t %s // -// CHECK-SPLIT-WITH-NOINL: "-split-dwarf=Enable" +// CHECK-SPLIT-WITH-NOINL: "-enable-split-dwarf" // CHECK-SPLIT-WITH-NOINL: "-debug-info-kind=limited" // CHECK-SPLIT-WITH-NOINL: "-split-dwarf-file" // RUN: %clang -target x86_64-unknown-linux-gnu -gsplit-dwarf -gmlt -S -### %s 2> %t // RUN: FileCheck -check-prefix=CHECK-GMLT-OVER-SPLIT < %t %s // -// CHECK-GMLT-OVER-SPLIT-NOT: "-split-dwarf=Enable" +// CHECK-GMLT-OVER-SPLIT-NOT: "-enable-split-dwarf" // CHECK-GMLT-OVER-SPLIT: "-debug-info-kind=line-tables-only" // CHECK-GMLT-OVER-SPLIT-NOT: "-split-dwarf-file" // RUN: %clang -target x86_64-unknown-linux-gnu -gmlt -gsplit-dwarf -S -### %s 2> %t // RUN: FileCheck -check-prefix=CHECK-SPLIT-OVER-GMLT < %t %s // -// CHECK-SPLIT-OVER-GMLT: "-split-dwarf=Enable" "-debug-info-kind=limited" +// CHECK-SPLIT-OVER-GMLT: "-enable-split-dwarf" "-debug-info-kind=limited" // CHECK-SPLIT-OVER-GMLT: "-split-dwarf-file" // RUN: %clang -target x86_64-unknown-linux-gnu -gsplit-dwarf -g0 -fno-split-dwarf-inlining -S -### %s 2> %t // RUN: FileCheck -check-prefix=CHECK-G0-OVER-SPLIT < %t %s // -// CHECK-G0-OVER-SPLIT-NOT: "-split-dwarf=Enable" +// CHECK-G0-OVER-SPLIT-NOT: "-enable-split-dwarf" // CHECK-G0-OVER-SPLIT-NOT: "-debug-info-kind // CHECK-G0-OVER-SPLIT-NOT: "-split-dwarf-file" // RUN: %clang -target x86_64-unknown-linux-gnu -gsplit-dwarf -g0 -S -### %s 2> %t // RUN: FileCheck -check-prefix=CHECK-G0-OVER-SPLIT < %t %s // -// CHECK-G0-OVER-SPLIT-NOT: "-split-dwarf=Enable" +// CHECK-G0-OVER-SPLIT-NOT: "-enable-split-dwarf" // CHECK-G0-OVER-SPLIT-NOT: "-debug-info-kind // CHECK-G0-OVER-SPLIT-NOT: "-split-dwarf-file" // RUN: %clang -target x86_64-unknown-linux-gnu -g0 -gsplit-dwarf -S -### %s 2> %t // RUN: FileCheck -check-prefix=CHECK-SPLIT-OVER-G0 < %t %s // -// CHECK-SPLIT-OVER-G0: "-split-dwarf=Enable" "-debug-info-kind=limited" +// CHECK-SPLIT-OVER-G0: "-enable-split-dwarf" "-debug-info-kind=limited" // CHECK-SPLIT-OVER-G0: "-split-dwarf-file" Index: test/Format/incomplete.cpp =================================================================== --- test/Format/incomplete.cpp +++ test/Format/incomplete.cpp @@ -1,6 +1,6 @@ // RUN: grep -Ev "// *[A-Z-]+:" %s | clang-format -style=LLVM -cursor=0 \ // RUN: | FileCheck -strict-whitespace %s -// CHECK: {{"IncompleteFormat": true}} +// CHECK: {{"IncompleteFormat": true, "Line": 2}} // CHECK: {{^int\ \i;$}} int i; // CHECK: {{^f \( g \(;$}} Index: test/Headers/stdatomic.c =================================================================== --- test/Headers/stdatomic.c +++ test/Headers/stdatomic.c @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -std=c11 -E %s | FileCheck %s +// RUN: %clang_cc1 -std=c11 -fms-compatibility -E %s | FileCheck %s #include int bool_lock_free = ATOMIC_BOOL_LOCK_FREE; Index: test/Index/Core/external-source-symbol-attr.m =================================================================== --- /dev/null +++ test/Index/Core/external-source-symbol-attr.m @@ -0,0 +1,100 @@ +// RUN: c-index-test core -print-source-symbols -- %s -target x86_64-apple-macosx10.7 | FileCheck %s + +#define EXT_DECL(mod_name) __attribute__((external_source_symbol(language="Swift", defined_in=mod_name))) +#define GEN_DECL(mod_name) __attribute__((external_source_symbol(language="Swift", defined_in=mod_name, generated_declaration))) +#define PUSH_GEN_DECL(mod_name) push(GEN_DECL(mod_name), apply_to=any(enum, objc_interface, objc_category, objc_protocol)) + +// This should not be indexed. +GEN_DECL("some_module") +@interface I1 +// CHECK-NOT: [[@LINE-1]]:12 | +-(void)method; +// CHECK-NOT: [[@LINE-1]]:8 | +@end + +EXT_DECL("some_module") +@interface I2 +// CHECK: [[@LINE-1]]:12 | class/ObjC | I2 | c:@M@some_module@objc(cs)I2 | {{.*}} | Decl | rel: 0 +-(void)method; +// CHECK: [[@LINE-1]]:8 | instance-method/ObjC | method | c:@M@some_module@objc(cs)I2(im)method | -[I2 method] | Decl,Dyn,RelChild | rel: 1 +@end + +void test1(I1 *o) { +// CHECK: [[@LINE-1]]:12 | class/ObjC | I1 | c:@M@some_module@objc(cs)I1 | + [o method]; + // CHECK: [[@LINE-1]]:6 | instance-method/ObjC | method | c:@M@some_module@objc(cs)I1(im)method | +} + +EXT_DECL("some_module") +@protocol ExtProt +// CHECK: [[@LINE-1]]:11 | protocol/ObjC | ExtProt | c:@M@some_module@objc(pl)ExtProt | +@end + +@interface I1(cat) +// CHECK: [[@LINE-1]]:15 | extension/ObjC | cat | c:@M@some_module@objc(cy)I1@cat | +-(void)cat_method; +// CHECK: [[@LINE-1]]:8 | instance-method/ObjC | cat_method | c:@M@some_module@objc(cs)I1(im)cat_method +@end + +EXT_DECL("cat_module") +@interface I1(cat2) +// CHECK: [[@LINE-1]]:15 | extension/ObjC | cat2 | c:@CM@cat_module@some_module@objc(cy)I1@cat2 | +-(void)cat_method2; +// CHECK: [[@LINE-1]]:8 | instance-method/ObjC | cat_method2 | c:@CM@cat_module@some_module@objc(cs)I1(im)cat_method2 +@end + +#define NS_ENUM(_name, _type) enum _name:_type _name; enum _name : _type + +#pragma clang attribute PUSH_GEN_DECL("modname") + +@interface I3 +// CHECK-NOT: [[@LINE-1]]:12 | +-(void)meth; +// CHECK-NOT: [[@LINE-1]]:8 | +@end + +@interface I3(cat) +// CHECK-NOT: [[@LINE-1]]:12 | +// CHECK-NOT: [[@LINE-2]]:15 | +-(void)meth2; +// CHECK-NOT: [[@LINE-1]]:8 | +@end + +@protocol ExtProt2 +// CHECK-NOT: [[@LINE-1]]:11 | +-(void)meth; +// CHECK-NOT: [[@LINE-1]]:8 | +@end + +typedef NS_ENUM(SomeEnum, int) { +// CHECK-NOT: [[@LINE-1]]:17 | + SomeEnumFirst = 0, + // CHECK-NOT: [[@LINE-1]]:3 | +}; + +#pragma clang attribute pop + +void test2(I3 *i3, id prot2, SomeEnum some) { + // CHECK: [[@LINE-1]]:12 | class/ObjC | I3 | c:@M@modname@objc(cs)I3 | + // CHECK: [[@LINE-2]]:23 | protocol/ObjC | ExtProt2 | c:@M@modname@objc(pl)ExtProt2 | + // CHECK: [[@LINE-3]]:40 | enum/C | SomeEnum | c:@M@modname@E@SomeEnum | + [i3 meth]; + // CHECK: [[@LINE-1]]:7 | instance-method/ObjC | meth | c:@M@modname@objc(cs)I3(im)meth | + [i3 meth2]; + // CHECK: [[@LINE-1]]:7 | instance-method/ObjC | meth2 | c:@CM@modname@objc(cs)I3(im)meth2 | + [prot2 meth]; + // CHECK: [[@LINE-1]]:10 | instance-method/ObjC | meth | c:@M@modname@objc(pl)ExtProt2(im)meth | + some = SomeEnumFirst; + // CHECK: [[@LINE-1]]:10 | enumerator/C | SomeEnumFirst | c:@M@modname@E@SomeEnum@SomeEnumFirst | +} + +#pragma clang attribute PUSH_GEN_DECL("other_mod_for_cat") +@interface I3(cat_other_mod) +-(void)meth_other_mod; +@end +#pragma clang attribute pop + +void test3(I3 *i3) { + [i3 meth_other_mod]; + // CHECK: [[@LINE-1]]:7 | instance-method/ObjC | meth_other_mod | c:@CM@other_mod_for_cat@modname@objc(cs)I3(im)meth_other_mod | +} Index: test/Index/Core/index-source.m =================================================================== --- test/Index/Core/index-source.m +++ test/Index/Core/index-source.m @@ -353,7 +353,8 @@ typedef NS_ENUM(AnotherEnum, int) { // CHECK-NOT: [[@LINE-1]]:17 | type-alias/C | AnotherEnum | -// CHECK: [[@LINE-2]]:17 | enum/C | AnotherEnum | [[AnotherEnum_USR:.*]] | {{.*}} | Ref,RelCont | rel: 1 +// CHECK-NOT: [[@LINE-2]]:17 | {{.*}} | Ref +// CHECK: [[@LINE-3]]:17 | enum/C | AnotherEnum | [[AnotherEnum_USR:.*]] | {{.*}} | Def | rel: 0 AnotherEnumFirst = 0, AnotherEnumSecond = 1, AnotherEnumThird = 2, Index: test/Modules/Inputs/template-default-args/a.h =================================================================== --- test/Modules/Inputs/template-default-args/a.h +++ test/Modules/Inputs/template-default-args/a.h @@ -14,3 +14,16 @@ template friend struct L; }; END + +namespace DeferredLookup { + template using X = U; + template void f() { (void) X(); } + template int n = X(); + template struct S { X xt; enum E : int; }; + template enum S::E : int { a = X() }; + + namespace Indirect { + template struct A {}; + template struct B { template using C = A; }; + } +} Index: test/Modules/Inputs/template-default-args/d.h =================================================================== --- test/Modules/Inputs/template-default-args/d.h +++ test/Modules/Inputs/template-default-args/d.h @@ -4,3 +4,10 @@ template friend struct L; }; END + +namespace DeferredLookup { + namespace Indirect { + template struct A {}; + template struct B { template using C = A; }; + } +} Index: test/Modules/template-default-args.cpp =================================================================== --- test/Modules/template-default-args.cpp +++ test/Modules/template-default-args.cpp @@ -44,3 +44,20 @@ I<> i; L<> *l; END + +namespace DeferredLookup { + template using X = U; + template void f() { (void) X(); } + template int n = X(); // expected-warning {{extension}} + template struct S { X xt; enum E : int; }; + template enum S::E : int { a = X() }; + + void test() { + f(); + n = 1; + S s; + S::E e = S::E::a; + + Indirect::B::C indirect; + } +} Index: test/Parser/cxx-modules-import.cpp =================================================================== --- test/Parser/cxx-modules-import.cpp +++ /dev/null @@ -1,58 +0,0 @@ -// RUN: rm -rf %t -// RUN: mkdir -p %t -// RUN: echo 'module x; int a, b;' > %t/x.cppm -// RUN: echo 'module x.y; int c;' > %t/x.y.cppm -// -// RUN: %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %t/x.cppm -o %t/x.pcm -// RUN: %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface -fmodule-file=%t/x.pcm %t/x.y.cppm -o %t/x.y.pcm -// -// RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \ -// RUN: -DTEST=1 -DMODULE_KIND=implementation -DMODULE_NAME=z -// RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \ -// RUN: -DTEST=2 -DMODULE_KIND=implementation -DMODULE_NAME=x -// RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \ -// RUN: -DTEST=3 -DMODULE_KIND= -DMODULE_NAME=z -// RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \ -// RUN: -DTEST=4 -DMODULE_KIND=partition -DMODULE_NAME=z -// RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \ -// RUN: -DTEST=5 -DMODULE_KIND=elderberry -DMODULE_NAME=z -// RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \ -// RUN: -DTEST=1 -DMODULE_KIND=implementation -DMODULE_NAME='z [[]]' -// RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \ -// RUN: -DTEST=6 -DMODULE_KIND=implementation -DMODULE_NAME='z [[fancy]]' -// RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \ -// RUN: -DTEST=7 -DMODULE_KIND=implementation -DMODULE_NAME='z [[maybe_unused]]' - -module MODULE_KIND MODULE_NAME; -#if TEST == 3 -// expected-error@-2 {{'module' declaration found while not building module interface}} -#elif TEST == 4 -// expected-error@-4 {{'module partition' declaration found while not building module interface}} -#elif TEST == 5 -// expected-error@-6 {{unexpected module kind 'elderberry'}} -#elif TEST == 6 -// expected-warning@-8 {{unknown attribute 'fancy' ignored}} -#elif TEST == 7 -// expected-error-re@-10 {{'maybe_unused' attribute cannot be applied to a module{{$}}}} -#endif - -int use_1 = a; -#if TEST != 2 -// expected-error@-2 {{declaration of 'a' must be imported from module 'x' before it is required}} -// expected-note@x.cppm:1 {{here}} -#endif - -import x; - -int use_2 = b; // ok - -import x [[]]; -import x [[foo]]; // expected-warning {{unknown attribute 'foo' ignored}} -import x [[noreturn]]; // expected-error {{'noreturn' attribute cannot be applied to a module import}} -import x [[blarg::noreturn]]; // expected-warning {{unknown attribute 'noreturn' ignored}} - -import x.y; -import x.; // expected-error {{expected a module name after module import}} -import .x; // expected-error {{expected a module name after module import}} - -import blarg; // expected-error {{module 'blarg' not found}} Index: test/Parser/cxx-modules-interface.cppm =================================================================== --- test/Parser/cxx-modules-interface.cppm +++ test/Parser/cxx-modules-interface.cppm @@ -1,13 +1,13 @@ // RUN: %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %s -o %t.pcm -verify // RUN: %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %s -o %t.pcm -verify -Dmodule=int -DERRORS -module foo; +export module foo; #ifndef ERRORS // expected-no-diagnostics #else -// expected-error@-4 {{expected module declaration at start of module interface}} +// FIXME: diagnose 'export' declaration in non-module +// FIXME: diagnose missing module-declaration when building module interface -// FIXME: support 'export module X;' and 'export { int n; module X; }' // FIXME: proclaimed-ownership-declarations? export { Index: test/Preprocessor/init.c =================================================================== --- test/Preprocessor/init.c +++ test/Preprocessor/init.c @@ -8846,6 +8846,16 @@ // WEBASSEMBLY32-NEXT:#define __CHAR32_TYPE__ unsigned int // WEBASSEMBLY32-NEXT:#define __CHAR_BIT__ 8 // WEBASSEMBLY32-NOT:#define __CHAR_UNSIGNED__ +// WEBASSEMBLY32-NEXT:#define __CLANG_ATOMIC_BOOL_LOCK_FREE 2 +// WEBASSEMBLY32-NEXT:#define __CLANG_ATOMIC_CHAR16_T_LOCK_FREE 2 +// WEBASSEMBLY32-NEXT:#define __CLANG_ATOMIC_CHAR32_T_LOCK_FREE 2 +// WEBASSEMBLY32-NEXT:#define __CLANG_ATOMIC_CHAR_LOCK_FREE 2 +// WEBASSEMBLY32-NEXT:#define __CLANG_ATOMIC_INT_LOCK_FREE 2 +// WEBASSEMBLY32-NEXT:#define __CLANG_ATOMIC_LLONG_LOCK_FREE 1 +// WEBASSEMBLY32-NEXT:#define __CLANG_ATOMIC_LONG_LOCK_FREE 2 +// WEBASSEMBLY32-NEXT:#define __CLANG_ATOMIC_POINTER_LOCK_FREE 2 +// WEBASSEMBLY32-NEXT:#define __CLANG_ATOMIC_SHORT_LOCK_FREE 2 +// WEBASSEMBLY32-NEXT:#define __CLANG_ATOMIC_WCHAR_T_LOCK_FREE 2 // WEBASSEMBLY32-NEXT:#define __CONSTANT_CFSTRINGS__ 1 // WEBASSEMBLY32-NEXT:#define __DBL_DECIMAL_DIG__ 17 // WEBASSEMBLY32-NEXT:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324 @@ -9162,6 +9172,16 @@ // WEBASSEMBLY64-NEXT:#define __CHAR32_TYPE__ unsigned int // WEBASSEMBLY64-NEXT:#define __CHAR_BIT__ 8 // WEBASSEMBLY64-NOT:#define __CHAR_UNSIGNED__ +// WEBASSEMBLY64-NEXT:#define __CLANG_ATOMIC_BOOL_LOCK_FREE 2 +// WEBASSEMBLY64-NEXT:#define __CLANG_ATOMIC_CHAR16_T_LOCK_FREE 2 +// WEBASSEMBLY64-NEXT:#define __CLANG_ATOMIC_CHAR32_T_LOCK_FREE 2 +// WEBASSEMBLY64-NEXT:#define __CLANG_ATOMIC_CHAR_LOCK_FREE 2 +// WEBASSEMBLY64-NEXT:#define __CLANG_ATOMIC_INT_LOCK_FREE 2 +// WEBASSEMBLY64-NEXT:#define __CLANG_ATOMIC_LLONG_LOCK_FREE 2 +// WEBASSEMBLY64-NEXT:#define __CLANG_ATOMIC_LONG_LOCK_FREE 2 +// WEBASSEMBLY64-NEXT:#define __CLANG_ATOMIC_POINTER_LOCK_FREE 2 +// WEBASSEMBLY64-NEXT:#define __CLANG_ATOMIC_SHORT_LOCK_FREE 2 +// WEBASSEMBLY64-NEXT:#define __CLANG_ATOMIC_WCHAR_T_LOCK_FREE 2 // WEBASSEMBLY64-NEXT:#define __CONSTANT_CFSTRINGS__ 1 // WEBASSEMBLY64-NEXT:#define __DBL_DECIMAL_DIG__ 17 // WEBASSEMBLY64-NEXT:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324 @@ -9637,3 +9657,36 @@ // AVR:#define __WCHAR_MAX__ 32767 // AVR:#define __WCHAR_TYPE__ int // AVR:#define __WINT_TYPE__ int + + +// RUN: %clang_cc1 -E -dM -ffreestanding \ +// RUN: -triple i686-windows-msvc -fms-compatibility < /dev/null \ +// RUN: | FileCheck -match-full-lines -check-prefix MSVC-X32 %s + +// RUN: %clang_cc1 -E -dM -ffreestanding \ +// RUN: -triple x86_64-windows-msvc -fms-compatibility < /dev/null \ +// RUN: | FileCheck -match-full-lines -check-prefix MSVC-X64 %s + +// MSVC-X32:#define __CLANG_ATOMIC_BOOL_LOCK_FREE 2 +// MSVC-X32-NEXT:#define __CLANG_ATOMIC_CHAR16_T_LOCK_FREE 2 +// MSVC-X32-NEXT:#define __CLANG_ATOMIC_CHAR32_T_LOCK_FREE 2 +// MSVC-X32-NEXT:#define __CLANG_ATOMIC_CHAR_LOCK_FREE 2 +// MSVC-X32-NEXT:#define __CLANG_ATOMIC_INT_LOCK_FREE 2 +// MSVC-X32-NEXT:#define __CLANG_ATOMIC_LLONG_LOCK_FREE 2 +// MSVC-X32-NEXT:#define __CLANG_ATOMIC_LONG_LOCK_FREE 2 +// MSVC-X32-NEXT:#define __CLANG_ATOMIC_POINTER_LOCK_FREE 2 +// MSVC-X32-NEXT:#define __CLANG_ATOMIC_SHORT_LOCK_FREE 2 +// MSVC-X32-NEXT:#define __CLANG_ATOMIC_WCHAR_T_LOCK_FREE 2 +// MSVC-X32-NOT:#define __GCC_ATOMIC{{.*}} + +// MSVC-X64:#define __CLANG_ATOMIC_BOOL_LOCK_FREE 2 +// MSVC-X64-NEXT:#define __CLANG_ATOMIC_CHAR16_T_LOCK_FREE 2 +// MSVC-X64-NEXT:#define __CLANG_ATOMIC_CHAR32_T_LOCK_FREE 2 +// MSVC-X64-NEXT:#define __CLANG_ATOMIC_CHAR_LOCK_FREE 2 +// MSVC-X64-NEXT:#define __CLANG_ATOMIC_INT_LOCK_FREE 2 +// MSVC-X64-NEXT:#define __CLANG_ATOMIC_LLONG_LOCK_FREE 2 +// MSVC-X64-NEXT:#define __CLANG_ATOMIC_LONG_LOCK_FREE 2 +// MSVC-X64-NEXT:#define __CLANG_ATOMIC_POINTER_LOCK_FREE 2 +// MSVC-X64-NEXT:#define __CLANG_ATOMIC_SHORT_LOCK_FREE 2 +// MSVC-X64-NEXT:#define __CLANG_ATOMIC_WCHAR_T_LOCK_FREE 2 +// MSVC-X86-NOT:#define __GCC_ATOMIC{{.*}} Index: test/Sema/atomic-ops.c =================================================================== --- test/Sema/atomic-ops.c +++ test/Sema/atomic-ops.c @@ -7,19 +7,29 @@ struct S { char c[3]; }; _Static_assert(__GCC_ATOMIC_BOOL_LOCK_FREE == 2, ""); +_Static_assert(__GCC_ATOMIC_BOOL_LOCK_FREE == __CLANG_ATOMIC_BOOL_LOCK_FREE, ""); _Static_assert(__GCC_ATOMIC_CHAR_LOCK_FREE == 2, ""); +_Static_assert(__GCC_ATOMIC_CHAR_LOCK_FREE == __CLANG_ATOMIC_CHAR_LOCK_FREE, ""); _Static_assert(__GCC_ATOMIC_CHAR16_T_LOCK_FREE == 2, ""); +_Static_assert(__GCC_ATOMIC_CHAR16_T_LOCK_FREE == __CLANG_ATOMIC_CHAR16_T_LOCK_FREE, ""); _Static_assert(__GCC_ATOMIC_CHAR32_T_LOCK_FREE == 2, ""); +_Static_assert(__GCC_ATOMIC_CHAR32_T_LOCK_FREE == __CLANG_ATOMIC_CHAR32_T_LOCK_FREE, ""); _Static_assert(__GCC_ATOMIC_WCHAR_T_LOCK_FREE == 2, ""); +_Static_assert(__GCC_ATOMIC_WCHAR_T_LOCK_FREE == __CLANG_ATOMIC_WCHAR_T_LOCK_FREE, ""); _Static_assert(__GCC_ATOMIC_SHORT_LOCK_FREE == 2, ""); +_Static_assert(__GCC_ATOMIC_SHORT_LOCK_FREE == __CLANG_ATOMIC_SHORT_LOCK_FREE, ""); _Static_assert(__GCC_ATOMIC_INT_LOCK_FREE == 2, ""); +_Static_assert(__GCC_ATOMIC_INT_LOCK_FREE == __CLANG_ATOMIC_INT_LOCK_FREE, ""); _Static_assert(__GCC_ATOMIC_LONG_LOCK_FREE == 2, ""); +_Static_assert(__GCC_ATOMIC_LONG_LOCK_FREE == __CLANG_ATOMIC_LONG_LOCK_FREE, ""); #ifdef __i386__ _Static_assert(__GCC_ATOMIC_LLONG_LOCK_FREE == 1, ""); #else _Static_assert(__GCC_ATOMIC_LLONG_LOCK_FREE == 2, ""); #endif +_Static_assert(__GCC_ATOMIC_LLONG_LOCK_FREE == __CLANG_ATOMIC_LLONG_LOCK_FREE, ""); _Static_assert(__GCC_ATOMIC_POINTER_LOCK_FREE == 2, ""); +_Static_assert(__GCC_ATOMIC_POINTER_LOCK_FREE == __CLANG_ATOMIC_POINTER_LOCK_FREE, ""); _Static_assert(__c11_atomic_is_lock_free(1), ""); _Static_assert(__c11_atomic_is_lock_free(2), ""); Index: test/Sema/warn-documentation.cpp =================================================================== --- test/Sema/warn-documentation.cpp +++ test/Sema/warn-documentation.cpp @@ -1210,3 +1210,75 @@ /*! @function test_function */ template <> int test_function (int arg); + +namespace AllowParamAndReturnsOnFunctionPointerVars { + +/** + * functionPointerVariable + * + * @param i is integer. + * @returns integer. + */ +int (*functionPointerVariable)(int i); + +struct HasFields { + /** + * functionPointerField + * + * @param i is integer. + * @returns integer. + */ + int (*functionPointerField)(int i); +}; + +// expected-warning@+5 {{'\returns' command used in a comment that is attached to a function returning void}} +/** + * functionPointerVariable + * + * \param p not here. + * \returns integer. + */ +void (*functionPointerVariableThatLeadsNowhere)(); + +// Still warn about param/returns commands for variables that don't specify +// the type directly: + +/** + * FunctionPointerTypedef + * + * \param i is integer. + * \returns integer. + */ +typedef int (*FunctionPointerTypedef)(int i); + +/** + * FunctionPointerTypealias + * + * \param i is integer. + * \returns integer. + */ +using FunctionPointerTypealias = int (*)(int i); + +// expected-warning@+5 {{'@param' command used in a comment that is not attached to a function declaration}} +// expected-warning@+5 {{'@returns' command used in a comment that is not attached to a function or method declaration}} +/** + * functionPointerVariable + * + * @param i is integer. + * @returns integer. + */ +FunctionPointerTypedef functionPointerTypedefVariable; + +struct HasMoreFields { + // expected-warning@+5 {{'\param' command used in a comment that is not attached to a function declaration}} + // expected-warning@+5 {{'\returns' command used in a comment that is not attached to a function or method declaration}} + /** + * functionPointerTypealiasField + * + * \param i is integer. + * \returns integer. + */ + FunctionPointerTypealias functionPointerTypealiasField; +}; + +} Index: test/Sema/warn-documentation.m =================================================================== --- test/Sema/warn-documentation.m +++ test/Sema/warn-documentation.m @@ -229,3 +229,65 @@ - (void) VarArgMeth : (id)arg, ... {} @end +/** + * blockPointerVariable + * + * @param i is integer. + * @returns integer. + */ +int (^blockPointerVariable)(int i); + +struct HasFields { + /** + * blockPointerField + * + * \param i is integer. + * \returns integer. + */ + int (^blockPointerFields)(int i); +}; + +// expected-warning@+5 {{'\returns' command used in a comment that is attached to a function returning void}} +/** + * functionPointerVariable + * + * \param p not here. + * \returns integer. + */ +void (^blockPointerVariableThatLeadsNowhere)(); + +@interface CheckFunctionBlockPointerVars { + /** + * functionPointerIVar + * + * @param i is integer. + * @returns integer. + */ + int (*functionPointerIVar)(int i); + + /** + * blockPointerIVar + * + * \param i is integer. + * \returns integer. + */ + int (^blockPointerIVar)(int i); +} + +/** + * functionPointerProperty + * + * @param i is integer. + * @returns integer. + */ +@property int (*functionPointerProperty)(int i); + +/** + * blockPointerProperty + * + * \param i is integer. + * \returns integer. + */ +@property int (^blockPointerProperty)(int i); + +@end Index: test/SemaCXX/MicrosoftCompatibility-cxx98.cpp =================================================================== --- test/SemaCXX/MicrosoftCompatibility-cxx98.cpp +++ /dev/null @@ -1,23 +0,0 @@ -// RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -std=c++98 -Wmicrosoft -verify -fms-compatibility -fexceptions -fcxx-exceptions - - -//MSVC allows forward enum declaration -enum ENUM; // expected-warning {{forward references to 'enum' types are a Microsoft extension}} -ENUM *var = 0; -ENUM var2 = (ENUM)3; -enum ENUM1* var3 = 0;// expected-warning {{forward references to 'enum' types are a Microsoft extension}} - -typedef void (*FnPtrTy)(); -void (*PR23733_1)() = static_cast((void *)0); // expected-warning {{static_cast between pointer-to-function and pointer-to-object is a Microsoft extension}} -void (*PR23733_2)() = FnPtrTy((void *)0); -void (*PR23733_3)() = (FnPtrTy)((void *)0); -void (*PR23733_4)() = reinterpret_cast((void *)0); - -long function_prototype(int a); -long (*function_ptr)(int a); - -void function_to_voidptr_conv() { - void *a1 = function_prototype; // expected-warning {{implicit conversion between pointer-to-function and pointer-to-object is a Microsoft extension}} - void *a2 = &function_prototype; // expected-warning {{implicit conversion between pointer-to-function and pointer-to-object is a Microsoft extension}} - void *a3 = function_ptr; // expected-warning {{implicit conversion between pointer-to-function and pointer-to-object is a Microsoft extension}} -} Index: test/SemaCXX/MicrosoftCompatibility.cpp =================================================================== --- test/SemaCXX/MicrosoftCompatibility.cpp +++ test/SemaCXX/MicrosoftCompatibility.cpp @@ -224,6 +224,15 @@ } +//MSVC allows forward enum declaration +enum ENUM; // expected-warning {{forward references to 'enum' types are a Microsoft extension}} +ENUM *var = 0; +ENUM var2 = (ENUM)3; +enum ENUM1* var3 = 0;// expected-warning {{forward references to 'enum' types are a Microsoft extension}} + +enum ENUM1 { kA }; +enum ENUM1; // This way round is fine. + enum ENUM2 { ENUM2_a = (enum ENUM2) 4, ENUM2_b = 0x9FFFFFFF, // expected-warning {{enumerator value is not representable in the underlying type 'int'}} @@ -269,3 +278,18 @@ f(0xffffffffffffffffi64); } } + +typedef void (*FnPtrTy)(); +void (*PR23733_1)() = static_cast((void *)0); // expected-warning {{static_cast between pointer-to-function and pointer-to-object is a Microsoft extension}} +void (*PR23733_2)() = FnPtrTy((void *)0); +void (*PR23733_3)() = (FnPtrTy)((void *)0); +void (*PR23733_4)() = reinterpret_cast((void *)0); + +long function_prototype(int a); +long (*function_ptr)(int a); + +void function_to_voidptr_conv() { + void *a1 = function_prototype; // expected-warning {{implicit conversion between pointer-to-function and pointer-to-object is a Microsoft extension}} + void *a2 = &function_prototype; // expected-warning {{implicit conversion between pointer-to-function and pointer-to-object is a Microsoft extension}} + void *a3 = function_ptr; // expected-warning {{implicit conversion between pointer-to-function and pointer-to-object is a Microsoft extension}} +} Index: test/SemaCXX/modules-ts.cppm =================================================================== --- test/SemaCXX/modules-ts.cppm +++ test/SemaCXX/modules-ts.cppm @@ -7,9 +7,9 @@ // expected-no-diagnostics #endif -module foo; +export module foo; #if TEST == 1 -// expected-error@-2 {{expected module declaration at start of module interface}} +// FIXME: diagnose export outside of module interface unit #elif TEST == 2 // CHECK-2: error: redefinition of module 'foo' #endif Index: test/SemaObjCXX/pr32725.mm =================================================================== --- /dev/null +++ test/SemaObjCXX/pr32725.mm @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -triple x86_64-apple-macosx -fsyntax-only -verify -x objective-c++ %s -o /dev/null +// REQUIRES: asserts + +struct objc_class { + unsigned long long bits; +}; +typedef struct objc_class *Class; +static void f(Class c) { (void)(c->bits & RW_HAS_OVERFLOW_REFCOUNT); } +// expected-error@-1{{use of undeclared identifier 'RW_HAS_OVERFLOW_REFCOUNT}} Index: test/SemaOpenCL/cl20-device-side-enqueue.cl =================================================================== --- test/SemaOpenCL/cl20-device-side-enqueue.cl +++ test/SemaOpenCL/cl20-device-side-enqueue.cl @@ -1,12 +1,14 @@ -// RUN: %clang_cc1 %s -cl-std=CL2.0 -triple "spir-unknown-unknown" -verify -pedantic -fsyntax-only -DB32 -// RUN: %clang_cc1 %s -cl-std=CL2.0 -triple "spir64-unknown-unknown" -verify -pedantic -fsyntax-only -Wconversion -DWCONV +// RUN: %clang_cc1 %s -cl-std=CL2.0 -triple "spir-unknown-unknown" -verify -pedantic -fsyntax-only -DB32 -DQUALS= +// RUN: %clang_cc1 %s -cl-std=CL2.0 -triple "spir-unknown-unknown" -verify -pedantic -fsyntax-only -DB32 -DQUALS="const volatile" +// RUN: %clang_cc1 %s -cl-std=CL2.0 -triple "spir64-unknown-unknown" -verify -pedantic -fsyntax-only -Wconversion -DWCONV -DQUALS= +// RUN: %clang_cc1 %s -cl-std=CL2.0 -triple "spir64-unknown-unknown" -verify -pedantic -fsyntax-only -Wconversion -DWCONV -DQUALS="const volatile" typedef struct {int a;} ndrange_t; // Diagnostic tests for different overloads of enqueue_kernel from Table 6.13.17.1 of OpenCL 2.0 Spec. kernel void enqueue_kernel_tests() { queue_t default_queue; unsigned flags = 0; - ndrange_t ndrange; + QUALS ndrange_t ndrange; clk_event_t evt; clk_event_t event_wait_list; clk_event_t event_wait_list2[] = {evt, evt}; Index: tools/clang-format/ClangFormat.cpp =================================================================== --- tools/clang-format/ClangFormat.cpp +++ tools/clang-format/ClangFormat.cpp @@ -276,14 +276,17 @@ } // Get new affected ranges after sorting `#includes`. Ranges = tooling::calculateRangesAfterReplacements(Replaces, Ranges); - bool IncompleteFormat = false; + FormattingAttemptStatus Status; Replacements FormatChanges = reformat(*FormatStyle, *ChangedCode, Ranges, - AssumedFileName, &IncompleteFormat); + AssumedFileName, &Status); Replaces = Replaces.merge(FormatChanges); if (OutputXML) { outs() << "\n\n"; + << (Status.FormatComplete ? "false" : "true") << "'"; + if (!Status.FormatComplete) + outs() << " line=" << Status.Line; + outs() << ">\n"; if (Cursor.getNumOccurrences() != 0) outs() << "" << FormatChanges.getShiftedCodePosition(CursorPosition) @@ -307,11 +310,15 @@ if (Rewrite.overwriteChangedFiles()) return true; } else { - if (Cursor.getNumOccurrences() != 0) + if (Cursor.getNumOccurrences() != 0) { outs() << "{ \"Cursor\": " << FormatChanges.getShiftedCodePosition(CursorPosition) << ", \"IncompleteFormat\": " - << (IncompleteFormat ? "true" : "false") << " }\n"; + << (Status.FormatComplete ? "false" : "true"); + if (!Status.FormatComplete) + outs() << ", \"Line\": " << Status.Line; + outs() << " }\n"; + } Rewrite.getEditBuffer(ID).write(outs()); } } Index: tools/clang-format/git-clang-format =================================================================== --- tools/clang-format/git-clang-format +++ tools/clang-format/git-clang-format @@ -23,6 +23,7 @@ Requires Python 2.7 """ +from __future__ import print_function import argparse import collections import contextlib @@ -138,15 +139,15 @@ if opts.verbose >= 1: ignored_files.difference_update(changed_lines) if ignored_files: - print 'Ignoring changes in the following files (wrong extension):' + print('Ignoring changes in the following files (wrong extension):') for filename in ignored_files: - print ' ', filename + print(' %s' % filename) if changed_lines: - print 'Running clang-format on the following files:' + print('Running clang-format on the following files:') for filename in changed_lines: - print ' ', filename + print(' %s' % filename) if not changed_lines: - print 'no modified files to format' + print('no modified files to format') return # The computed diff outputs absolute paths, so we must cd before accessing # those files. @@ -163,20 +164,20 @@ binary=opts.binary, style=opts.style) if opts.verbose >= 1: - print 'old tree:', old_tree - print 'new tree:', new_tree + print('old tree: %s' % old_tree) + print('new tree: %s' % new_tree) if old_tree == new_tree: if opts.verbose >= 0: - print 'clang-format did not modify any files' + print('clang-format did not modify any files') elif opts.diff: print_diff(old_tree, new_tree) else: changed_files = apply_changes(old_tree, new_tree, force=opts.force, patch_mode=opts.patch) if (opts.verbose >= 0 and not opts.patch) or opts.verbose >= 1: - print 'changed files:' + print('changed files:') for filename in changed_files: - print ' ', filename + print(' %s' % filename) def load_git_config(non_string_options=None): @@ -320,7 +321,7 @@ `allowed_extensions` must be a collection of lowercase file extensions, excluding the period.""" allowed_extensions = frozenset(allowed_extensions) - for filename in dictionary.keys(): + for filename in list(dictionary.keys()): base_ext = filename.rsplit('.', 1) if len(base_ext) == 1 or base_ext[1].lower() not in allowed_extensions: del dictionary[filename] @@ -344,8 +345,13 @@ """Run clang-format on each file and save the result to a git tree. Returns the object ID (SHA-1) of the created tree.""" + def iteritems(container): + try: + return container.iteritems() # Python 2 + except AttributeError: + return container.items() # Python 3 def index_info_generator(): - for filename, line_ranges in changed_lines.iteritems(): + for filename, line_ranges in iteritems(changed_lines): if revision: git_metadata_cmd = ['git', 'ls-tree', '%s:%s' % (revision, os.path.dirname(filename)), @@ -356,6 +362,9 @@ mode = oct(int(stdout.split()[0], 8)) else: mode = oct(os.stat(filename).st_mode) + # Adjust python3 octal format so that it matches what git expects + if mode.startswith('0o'): + mode = '0' + mode[2:] blob_id = clang_format_to_blob(filename, line_ranges, revision=revision, binary=binary, @@ -488,10 +497,10 @@ if not force: unstaged_files = run('git', 'diff-files', '--name-status', *changed_files) if unstaged_files: - print >>sys.stderr, ('The following files would be modified but ' - 'have unstaged changes:') - print >>sys.stderr, unstaged_files - print >>sys.stderr, 'Please commit, stage, or stash them first.' + print('The following files would be modified but ' + 'have unstaged changes:', file=sys.stderr) + print(unstaged_files, file=sys.stderr) + print('Please commit, stage, or stash them first.', file=sys.stderr) sys.exit(2) if patch_mode: # In patch mode, we could just as well create an index from the new tree @@ -521,20 +530,20 @@ if p.returncode == 0: if stderr: if verbose: - print >>sys.stderr, '`%s` printed to stderr:' % ' '.join(args) - print >>sys.stderr, stderr.rstrip() + print('`%s` printed to stderr:' % ' '.join(args), file=sys.stderr) + print(stderr.rstrip(), file=sys.stderr) if strip: stdout = stdout.rstrip('\r\n') return stdout if verbose: - print >>sys.stderr, '`%s` returned %s' % (' '.join(args), p.returncode) + print('`%s` returned %s' % (' '.join(args), p.returncode), file=sys.stderr) if stderr: - print >>sys.stderr, stderr.rstrip() + print(stderr.rstrip(), file=sys.stderr) sys.exit(2) def die(message): - print >>sys.stderr, 'error:', message + print('error:', message, file=sys.stderr) sys.exit(2) Index: unittests/Format/CleanupTest.cpp =================================================================== --- unittests/Format/CleanupTest.cpp +++ unittests/Format/CleanupTest.cpp @@ -292,7 +292,7 @@ } inline std::string apply(StringRef Code, - const tooling::Replacements Replaces) { + const tooling::Replacements &Replaces) { auto CleanReplaces = cleanupAroundReplacements(Code, Replaces, Style); EXPECT_TRUE(static_cast(CleanReplaces)) << llvm::toString(CleanReplaces.takeError()) << "\n"; @@ -302,8 +302,7 @@ } inline std::string formatAndApply(StringRef Code, - const tooling::Replacements Replaces) { - + const tooling::Replacements &Replaces) { auto CleanReplaces = cleanupAroundReplacements(Code, Replaces, Style); EXPECT_TRUE(static_cast(CleanReplaces)) << llvm::toString(CleanReplaces.takeError()) << "\n"; Index: unittests/Format/FormatTest.cpp =================================================================== --- unittests/Format/FormatTest.cpp +++ unittests/Format/FormatTest.cpp @@ -30,24 +30,25 @@ class FormatTest : public ::testing::Test { protected: - enum IncompleteCheck { - IC_ExpectComplete, - IC_ExpectIncomplete, - IC_DoNotCheck + enum StatusCheck { + SC_ExpectComplete, + SC_ExpectIncomplete, + SC_DoNotCheck }; std::string format(llvm::StringRef Code, const FormatStyle &Style = getLLVMStyle(), - IncompleteCheck CheckIncomplete = IC_ExpectComplete) { + StatusCheck CheckComplete = SC_ExpectComplete) { DEBUG(llvm::errs() << "---\n"); DEBUG(llvm::errs() << Code << "\n\n"); std::vector Ranges(1, tooling::Range(0, Code.size())); - bool IncompleteFormat = false; + FormattingAttemptStatus Status; tooling::Replacements Replaces = - reformat(Style, Code, Ranges, "", &IncompleteFormat); - if (CheckIncomplete != IC_DoNotCheck) { - bool ExpectedIncompleteFormat = CheckIncomplete == IC_ExpectIncomplete; - EXPECT_EQ(ExpectedIncompleteFormat, IncompleteFormat) << Code << "\n\n"; + reformat(Style, Code, Ranges, "", &Status); + if (CheckComplete != SC_DoNotCheck) { + bool ExpectedCompleteFormat = CheckComplete == SC_ExpectComplete; + EXPECT_EQ(ExpectedCompleteFormat, Status.FormatComplete) + << Code << "\n\n"; } ReplacementCount = Replaces.size(); auto Result = applyAllReplacements(Code, Replaces); @@ -83,7 +84,7 @@ void verifyIncompleteFormat(llvm::StringRef Code, const FormatStyle &Style = getLLVMStyle()) { EXPECT_EQ(Code.str(), - format(test::messUp(Code), Style, IC_ExpectIncomplete)); + format(test::messUp(Code), Style, SC_ExpectIncomplete)); } void verifyGoogleFormat(llvm::StringRef Code) { @@ -98,7 +99,7 @@ /// \brief Verify that clang-format does not crash on the given input. void verifyNoCrash(llvm::StringRef Code, const FormatStyle &Style = getLLVMStyle()) { - format(Code, Style, IC_DoNotCheck); + format(Code, Style, SC_DoNotCheck); } int ReplacementCount; @@ -6189,7 +6190,7 @@ // Deeply nested part is untouched, rest is formatted. EXPECT_EQ(std::string("int i;\n") + Code + "int j;\n", format(std::string("int i;\n") + Code + "int j;\n", - getLLVMStyle(), IC_ExpectIncomplete)); + getLLVMStyle(), SC_ExpectIncomplete)); } //===----------------------------------------------------------------------===// Index: unittests/Format/FormatTestComments.cpp =================================================================== --- unittests/Format/FormatTestComments.cpp +++ unittests/Format/FormatTestComments.cpp @@ -29,24 +29,25 @@ class FormatTestComments : public ::testing::Test { protected: - enum IncompleteCheck { - IC_ExpectComplete, - IC_ExpectIncomplete, - IC_DoNotCheck + enum StatusCheck { + SC_ExpectComplete, + SC_ExpectIncomplete, + SC_DoNotCheck }; std::string format(llvm::StringRef Code, const FormatStyle &Style = getLLVMStyle(), - IncompleteCheck CheckIncomplete = IC_ExpectComplete) { + StatusCheck CheckComplete = SC_ExpectComplete) { DEBUG(llvm::errs() << "---\n"); DEBUG(llvm::errs() << Code << "\n\n"); std::vector Ranges(1, tooling::Range(0, Code.size())); - bool IncompleteFormat = false; + FormattingAttemptStatus Status; tooling::Replacements Replaces = - reformat(Style, Code, Ranges, "", &IncompleteFormat); - if (CheckIncomplete != IC_DoNotCheck) { - bool ExpectedIncompleteFormat = CheckIncomplete == IC_ExpectIncomplete; - EXPECT_EQ(ExpectedIncompleteFormat, IncompleteFormat) << Code << "\n\n"; + reformat(Style, Code, Ranges, "", &Status); + if (CheckComplete != SC_DoNotCheck) { + bool ExpectedCompleteFormat = CheckComplete == SC_ExpectComplete; + EXPECT_EQ(ExpectedCompleteFormat, Status.FormatComplete) + << Code << "\n\n"; } ReplacementCount = Replaces.size(); auto Result = applyAllReplacements(Code, Replaces); @@ -73,7 +74,7 @@ /// \brief Verify that clang-format does not crash on the given input. void verifyNoCrash(llvm::StringRef Code, const FormatStyle &Style = getLLVMStyle()) { - format(Code, Style, IC_DoNotCheck); + format(Code, Style, SC_DoNotCheck); } int ReplacementCount; Index: unittests/Format/FormatTestJS.cpp =================================================================== --- unittests/Format/FormatTestJS.cpp +++ unittests/Format/FormatTestJS.cpp @@ -24,10 +24,10 @@ DEBUG(llvm::errs() << "---\n"); DEBUG(llvm::errs() << Code << "\n\n"); std::vector Ranges(1, tooling::Range(Offset, Length)); - bool IncompleteFormat = false; + FormattingAttemptStatus Status; tooling::Replacements Replaces = - reformat(Style, Code, Ranges, "", &IncompleteFormat); - EXPECT_FALSE(IncompleteFormat); + reformat(Style, Code, Ranges, "", &Status); + EXPECT_TRUE(Status.FormatComplete); auto Result = applyAllReplacements(Code, Replaces); EXPECT_TRUE(static_cast(Result)); DEBUG(llvm::errs() << "\n" << *Result << "\n\n"); Index: unittests/Format/FormatTestObjC.cpp =================================================================== --- unittests/Format/FormatTestObjC.cpp +++ unittests/Format/FormatTestObjC.cpp @@ -33,23 +33,24 @@ Style.Language = FormatStyle::LK_ObjC; } - enum IncompleteCheck { - IC_ExpectComplete, - IC_ExpectIncomplete, - IC_DoNotCheck + enum StatusCheck { + SC_ExpectComplete, + SC_ExpectIncomplete, + SC_DoNotCheck }; std::string format(llvm::StringRef Code, - IncompleteCheck CheckIncomplete = IC_ExpectComplete) { + StatusCheck CheckComplete = SC_ExpectComplete) { DEBUG(llvm::errs() << "---\n"); DEBUG(llvm::errs() << Code << "\n\n"); std::vector Ranges(1, tooling::Range(0, Code.size())); - bool IncompleteFormat = false; + FormattingAttemptStatus Status; tooling::Replacements Replaces = - reformat(Style, Code, Ranges, "", &IncompleteFormat); - if (CheckIncomplete != IC_DoNotCheck) { - bool ExpectedIncompleteFormat = CheckIncomplete == IC_ExpectIncomplete; - EXPECT_EQ(ExpectedIncompleteFormat, IncompleteFormat) << Code << "\n\n"; + reformat(Style, Code, Ranges, "", &Status); + if (CheckComplete != SC_DoNotCheck) { + bool ExpectedCompleteFormat = CheckComplete == SC_ExpectComplete; + EXPECT_EQ(ExpectedCompleteFormat, Status.FormatComplete) + << Code << "\n\n"; } auto Result = applyAllReplacements(Code, Replaces); EXPECT_TRUE(static_cast(Result)); @@ -62,7 +63,7 @@ } void verifyIncompleteFormat(StringRef Code) { - EXPECT_EQ(Code.str(), format(test::messUp(Code), IC_ExpectIncomplete)); + EXPECT_EQ(Code.str(), format(test::messUp(Code), SC_ExpectIncomplete)); } FormatStyle Style; Index: unittests/Format/FormatTestSelective.cpp =================================================================== --- unittests/Format/FormatTestSelective.cpp +++ unittests/Format/FormatTestSelective.cpp @@ -24,10 +24,10 @@ DEBUG(llvm::errs() << "---\n"); DEBUG(llvm::errs() << Code << "\n\n"); std::vector Ranges(1, tooling::Range(Offset, Length)); - bool IncompleteFormat = false; + FormattingAttemptStatus Status; tooling::Replacements Replaces = - reformat(Style, Code, Ranges, "", &IncompleteFormat); - EXPECT_FALSE(IncompleteFormat) << Code << "\n\n"; + reformat(Style, Code, Ranges, "", &Status); + EXPECT_TRUE(Status.FormatComplete) << Code << "\n\n"; auto Result = applyAllReplacements(Code, Replaces); EXPECT_TRUE(static_cast(Result)); DEBUG(llvm::errs() << "\n" << *Result << "\n\n"); Index: unittests/Format/NamespaceEndCommentsFixerTest.cpp =================================================================== --- unittests/Format/NamespaceEndCommentsFixerTest.cpp +++ unittests/Format/NamespaceEndCommentsFixerTest.cpp @@ -23,7 +23,7 @@ protected: std::string fixNamespaceEndComments(llvm::StringRef Code, - std::vector Ranges, + const std::vector &Ranges, const FormatStyle &Style = getLLVMStyle()) { DEBUG(llvm::errs() << "---\n"); DEBUG(llvm::errs() << Code << "\n\n"); Index: utils/TableGen/ClangAttrEmitter.cpp =================================================================== --- utils/TableGen/ClangAttrEmitter.cpp +++ utils/TableGen/ClangAttrEmitter.cpp @@ -1928,58 +1928,14 @@ OS << "}\n\n"; } -template -static void forEachUniqueSpelling(const Record &Attr, Fn &&F) { - std::vector Spellings = GetFlattenedSpellings(Attr); - SmallDenseSet Seen; - for (const FlattenedSpelling &S : Spellings) { - if (Seen.insert(S.name()).second) - F(S); - } -} - -/// \brief Emits the first-argument-is-type property for attributes. -static void emitClangAttrTypeArgList(RecordKeeper &Records, raw_ostream &OS) { - OS << "#if defined(CLANG_ATTR_TYPE_ARG_LIST)\n"; - std::vector Attrs = Records.getAllDerivedDefinitions("Attr"); - - for (const auto *Attr : Attrs) { - // Determine whether the first argument is a type. - std::vector Args = Attr->getValueAsListOfDefs("Args"); - if (Args.empty()) - continue; - - if (Args[0]->getSuperClasses().back().first->getName() != "TypeArgument") - continue; - - // All these spellings take a single type argument. - forEachUniqueSpelling(*Attr, [&](const FlattenedSpelling &S) { - OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n"; - }); +static bool isIdentifierArgument(const Record &Attr) { + std::vector ArgRecords = Attr.getValueAsListOfDefs("Args"); + if (ArgRecords.empty()) { + return false; } - OS << "#endif // CLANG_ATTR_TYPE_ARG_LIST\n\n"; -} -/// \brief Emits the parse-arguments-in-unevaluated-context property for -/// attributes. -static void emitClangAttrArgContextList(RecordKeeper &Records, raw_ostream &OS) { - OS << "#if defined(CLANG_ATTR_ARG_CONTEXT_LIST)\n"; - ParsedAttrMap Attrs = getParsedAttrList(Records); - for (const auto &I : Attrs) { - const Record &Attr = *I.second; + const Record *Arg = ArgRecords[0]; - if (!Attr.getValueAsBit("ParseArgumentsAsUnevaluated")) - continue; - - // All these spellings take are parsed unevaluated. - forEachUniqueSpelling(Attr, [&](const FlattenedSpelling &S) { - OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n"; - }); - } - OS << "#endif // CLANG_ATTR_ARG_CONTEXT_LIST\n\n"; -} - -static bool isIdentifierArgument(Record *Arg) { return !Arg->getSuperClasses().empty() && llvm::StringSwitch(Arg->getSuperClasses().back().first->getName()) .Case("IdentifierArgument", true) @@ -1988,23 +1944,18 @@ .Default(false); } -// Emits the first-argument-is-identifier property for attributes. -static void emitClangAttrIdentifierArgList(RecordKeeper &Records, raw_ostream &OS) { - OS << "#if defined(CLANG_ATTR_IDENTIFIER_ARG_LIST)\n"; - std::vector Attrs = Records.getAllDerivedDefinitions("Attr"); - - for (const auto *Attr : Attrs) { - // Determine whether the first argument is an identifier. - std::vector Args = Attr->getValueAsListOfDefs("Args"); - if (Args.empty() || !isIdentifierArgument(Args[0])) - continue; +// Is the first arg of attr a type argument +static bool isTypeArgument(const Record &Attr) { + std::vector ArgRecords = Attr.getValueAsListOfDefs("Args"); - // All these spellings take an identifier argument. - forEachUniqueSpelling(*Attr, [&](const FlattenedSpelling &S) { - OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n"; - }); + if (ArgRecords.empty()) { + return false; } - OS << "#endif // CLANG_ATTR_IDENTIFIER_ARG_LIST\n\n"; + + const Record *Arg = ArgRecords[0]; + + return !Arg->getSuperClasses().empty() && \ + ArgRecords[0]->getSuperClasses().back().first->getName() == "TypeArgument"; } namespace clang { @@ -2766,40 +2717,6 @@ OS << "}\n"; } -void EmitClangAttrSpellingListIndex(RecordKeeper &Records, raw_ostream &OS) { - emitSourceFileHeader("Code to translate different attribute spellings " - "into internal identifiers", OS); - - OS << " switch (AttrKind) {\n"; - - ParsedAttrMap Attrs = getParsedAttrList(Records); - for (const auto &I : Attrs) { - const Record &R = *I.second; - std::vector Spellings = GetFlattenedSpellings(R); - OS << " case AT_" << I.first << ": {\n"; - for (unsigned I = 0; I < Spellings.size(); ++ I) { - OS << " if (Name == \"" << Spellings[I].name() << "\" && " - << "SyntaxUsed == " - << StringSwitch(Spellings[I].variety()) - .Case("GNU", 0) - .Case("CXX11", 1) - .Case("Declspec", 2) - .Case("Microsoft", 3) - .Case("Keyword", 4) - .Case("Pragma", 5) - .Default(0) - << " && Scope == \"" << Spellings[I].nameSpace() << "\")\n" - << " return " << I << ";\n"; - } - - OS << " break;\n"; - OS << " }\n"; - } - - OS << " }\n"; - OS << " return 0;\n"; -} - // Emits code used by RecursiveASTVisitor to visit attributes void EmitClangAttrASTVisitor(RecordKeeper &Records, raw_ostream &OS) { emitSourceFileHeader("Used by RecursiveASTVisitor to visit attributes.", OS); @@ -2980,7 +2897,7 @@ // If there is a variadic argument, we will set the optional argument count // to its largest value. Since it's currently a 4-bit number, we set it to 15. OS << " NumArgs = " << ArgCount << ";\n"; - Os << " OptArgs = " << (HasVariadic ? 15 : OptCount) << ";\n"; + OS << " OptArgs = " << (HasVariadic ? 15 : OptCount) << ";\n"; } static void GenerateDefaultAppertainsTo(raw_ostream &OS) { @@ -3203,17 +3120,16 @@ std::string SubjectType = GetSubjectWithSuffix(Subject); OS << " if (isa<" << SubjectType << ">(D)) return true;\n"; } - - bool Warn = SubjectObj->getValueAsDef("Diag")->getValueAsBit("Warn"); - OS << " S.Diag(Attr.getLoc(), diag::"; - OS << (Warn ? "warn_attr_wrong_decl_type" : "err_attr_wrong_decl_type"); - OS << ")\n"; - OS << " << Attr.getName() << "; - OS << CalculateDiagnostic(*SubjectObj) << ";\n"; - OS << " return false;\n"; - OS << " }\n\n"; } + bool Warn = SubjectObj->getValueAsDef("Diag")->getValueAsBit("Warn"); + OS << " S.Diag(Attr.getLoc(), diag::"; + OS << (Warn ? "warn_attr_wrong_decl_type" : "err_attr_wrong_decl_type"); + OS << ")\n"; + OS << " << Attr.getName() << "; + OS << CalculateDiagnostic(*SubjectObj) << ";\n"; + OS << " return false;\n"; + OS << " }\n\n"; } static void @@ -3238,7 +3154,8 @@ // that was generated for GenerateAppertainsTo to check if the declaration // is valid. if ((*I)->isSubClassOf("SubsetSubject")) - OS << functionNameForCustomAppertainsTo(**I) << "(D)"; + //OS << functionNameForCustomAppertainsTo(**I) << "(D)"; + OS << "false;\n"; else OS << "isa<" << GetSubjectWithSuffix(*I) << ">(D)"; @@ -3285,7 +3202,7 @@ OS << "const {\n"; OS << " if (" << Test << ")\n"; OS << " return true;\n\n"; - OS << " S.Diag(Attr.getLoc, diag::warn_attr_ignored) "; + OS << " S.Diag(Attr.getLoc(), diag::warn_attr_ignored) "; OS << "<< Attr.getName();\n"; OS << " return false;\n"; OS << " }\n\n"; @@ -3338,7 +3255,7 @@ OS << " virtual bool existsInTarget(const TargetInfo &Target) const {\n"; OS << " const llvm::Triple &T = Target.getTriple();\n"; OS << " return " << Test << ";\n"; - OS << " \n\n"; + OS << " }\n\n"; } static void GenerateDefaultSpellingIndexToSemanticSpelling(raw_ostream &OS) { @@ -3348,32 +3265,6 @@ OS << "}\n\n"; } -static void GenerateSpellingIndexToSemanticSpelling(const Record &Attr, - raw_ostream &OS) { - // If the attribute does not have a semantic form, we can bail out early. - if (!Attr.getValueAsBit("ASTNode")) - return; - - std::vector Spellings = GetFlattenedSpellings(Attr); - - // If there are zero or one spellings, or all of the spellings share the same - // name, we can also bail out early. - if (Spellings.size() <= 1 || SpellingNamesAreCommon(Spellings)) - return; - - // Generate the enumeration we will use for the mapping. - SemanticSpellingMap SemanticToSyntacticMap; - std::string Enum = CreateSemanticSpellings(Spellings, SemanticToSyntacticMap); - std::string Name = Attr.getName().str() + "AttrSpellingMap"; - - OS << " virtual unsigned spellingIndexToSemanticSpelling("; - OS << "const AttributeList &Attr) const {\n"; - OS << Enum; - OS << " unsigned Idx = Attr.getAttributeSpellingListIndex();\n"; - WriteSemanticSpellingSwitch("Idx", SemanticToSyntacticMap, OS); - OS << " \n\n"; -} - static bool IsKnownToGCC(const Record &Attr) { // Look at the spellings for this subject; if there are any spellings which // claim to be known to GCC, the attribute is known to GCC. @@ -3408,14 +3299,16 @@ // We need to generate struct instances based off ParsedAttrInfo from // AttributeList.cpp. - const Record &Attr = *I->second; + const Record &Attr = *I.second; const std::string &AttrName = I.first; std::vector Spellings = GetFlattenedSpellings(Attr); + SemanticSpellingMap SemanticToSyntacticMap; + CreateSemanticSpellings(Spellings, SemanticToSyntacticMap); unsigned SpellingIdx = 0; for (const auto &S : Spellings) { std::string Spelling; if (S.variety() == "CXX11") { - Spelling += S.namespace(); + Spelling += S.nameSpace(); Spelling += "::"; } @@ -3423,13 +3316,25 @@ std::string AttrInfoName = "AttrInfo" + std::to_string(SpellingIdx) + AttrName; OS << "struct " << AttrInfoName << " : public ParsedAttrInfo {\n"; OS << " " << AttrInfoName << "() {\n"; + OS << " SpellingListIndex = " << SpellingIdx << ";\n"; + // If the attribute does not have a semantic form, has at most one + // spelling, or all spellings share the same name, then it has no + // semantic spelling. + if (!Attr.getValueAsBit("ASTNode") || Spellings.size() <= 1 || \ + SpellingNamesAreCommon(Spellings)) { + OS << " SemanticSpelling = UINT_MAX;\n"; + } else { + OS << " SemanticSpelling = " << Attr.getName() \ + << "Attr::" << SemanticToSyntacticMap[SpellingIdx] << ";\n"; + } + if (Attr.getValueAsBit("Ignored")) { OS << " AttrKind = AttributeList::IgnoredAttribute;\n"; } else { OS << " AttrKind = AttributeList::AT_" << AttrName << ";\n"; } - OS << " Syntax = AttributeList::AS_" << S.variety() << ";\n"; + OS << " Syntax = AttributeList::AS_" << S.variety() << ";\n"; emitArgInfo(Attr, OS); OS << " HasCustomParsing = "; OS << Attr.getValueAsBit("HasCustomParsing") << ";\n"; @@ -3441,13 +3346,20 @@ OS << Attr.isSubClassOf("StmtAttr") << ";\n"; OS << " IsKnownToGCC = "; OS << IsKnownToGCC(Attr) << ";\n"; + OS << " IsUnevaluatedArgContext = "; + OS << Attr.getValueAsBit("ParseArgumentsAsUnevaluated") << ";\n"; + OS << " IsIdentifierArg = "; + OS << isIdentifierArgument(Attr) << ";\n"; + OS << " IsTypeArg = "; + OS << isTypeArgument(Attr) << ";\n"; + OS << " IsLateParsed = "; + OS << Attr.getValueAsBit("LateParsed") << ";\n"; OS << " }\n"; GenerateAppertainsTo(Attr, OS); GenerateLangOptRequirements(Attr, OS); GenerateTargetRequirements(Attr, Dupes, OS); - GenerateSpellingIndexToSemanticSpelling(Attr, OS); OS << "};\n"; - OS << "static AttrInfoRegistry::Add<" AttrInfoName << "> " << AttrInfoName << "Instance(\"" << Spelling << "\",\"\");\n"; + OS << "static AttrInfoRegistry::Add<" << AttrInfoName << "> " << AttrInfoName << "Instance(\"" << Spelling << "\",\"\");\n"; ++SpellingIdx; } } @@ -3492,15 +3404,6 @@ OS << " }\n"; } -void EmitClangAttrParserStringSwitches(RecordKeeper &Records, - raw_ostream &OS) { - emitSourceFileHeader("Parser-related llvm::StringSwitch cases", OS); - emitClangAttrArgContextList(Records, OS); - emitClangAttrIdentifierArgList(Records, OS); - emitClangAttrTypeArgList(Records, OS); - emitClangAttrLateParsedList(Records, OS); -} - void EmitClangAttrSubjectMatchRulesParserStringSwitches(RecordKeeper &Records, raw_ostream &OS) { getPragmaAttributeSupport(Records).generateParsingHelpers(OS); Index: utils/TableGen/TableGen.cpp =================================================================== --- utils/TableGen/TableGen.cpp +++ utils/TableGen/TableGen.cpp @@ -24,7 +24,6 @@ enum ActionType { GenClangAttrClasses, - GenClangAttrParserStringSwitches, GenClangAttrSubjectMatchRulesParserStringSwitches, GenClangAttrImpl, GenClangAttrList, @@ -32,12 +31,10 @@ GenClangAttrPCHRead, GenClangAttrPCHWrite, GenClangAttrHasAttributeImpl, - GenClangAttrSpellingListIndex, GenClangAttrASTVisitor, GenClangAttrTemplateInstantiate, GenClangAttrParsedAttrList, GenClangAttrParsedAttrImpl, - GenClangAttrParsedAttrKinds, GenClangAttrDump, GenClangDiagsDefs, GenClangDiagGroups, @@ -66,9 +63,6 @@ cl::values( clEnumValN(GenClangAttrClasses, "gen-clang-attr-classes", "Generate clang attribute clases"), - clEnumValN(GenClangAttrParserStringSwitches, - "gen-clang-attr-parser-string-switches", - "Generate all parser-related attribute string switches"), clEnumValN(GenClangAttrSubjectMatchRulesParserStringSwitches, "gen-clang-attr-subject-match-rules-parser-string-switches", "Generate all parser-related attribute subject match rule" @@ -87,9 +81,6 @@ clEnumValN(GenClangAttrHasAttributeImpl, "gen-clang-attr-has-attribute-impl", "Generate a clang attribute spelling list"), - clEnumValN(GenClangAttrSpellingListIndex, - "gen-clang-attr-spelling-index", - "Generate a clang attribute spelling index"), clEnumValN(GenClangAttrASTVisitor, "gen-clang-attr-ast-visitor", "Generate a recursive AST visitor for clang attributes"), clEnumValN(GenClangAttrTemplateInstantiate, @@ -101,9 +92,6 @@ clEnumValN(GenClangAttrParsedAttrImpl, "gen-clang-attr-parsed-attr-impl", "Generate the clang parsed attribute helpers"), - clEnumValN(GenClangAttrParsedAttrKinds, - "gen-clang-attr-parsed-attr-kinds", - "Generate a clang parsed attribute kinds"), clEnumValN(GenClangAttrDump, "gen-clang-attr-dump", "Generate clang attribute dumper"), clEnumValN(GenClangDiagsDefs, "gen-clang-diags-defs", @@ -162,9 +150,6 @@ case GenClangAttrClasses: EmitClangAttrClass(Records, OS); break; - case GenClangAttrParserStringSwitches: - EmitClangAttrParserStringSwitches(Records, OS); - break; case GenClangAttrSubjectMatchRulesParserStringSwitches: EmitClangAttrSubjectMatchRulesParserStringSwitches(Records, OS); break; @@ -186,9 +171,6 @@ case GenClangAttrHasAttributeImpl: EmitClangAttrHasAttrImpl(Records, OS); break; - case GenClangAttrSpellingListIndex: - EmitClangAttrSpellingListIndex(Records, OS); - break; case GenClangAttrASTVisitor: EmitClangAttrASTVisitor(Records, OS); break; @@ -201,9 +183,6 @@ case GenClangAttrParsedAttrImpl: EmitClangAttrParsedAttrImpl(Records, OS); break; - case GenClangAttrParsedAttrKinds: - EmitClangAttrParsedAttrKinds(Records, OS); - break; case GenClangAttrDump: EmitClangAttrDump(Records, OS); break; Index: utils/TableGen/TableGenBackends.h =================================================================== --- utils/TableGen/TableGenBackends.h +++ utils/TableGen/TableGenBackends.h @@ -32,7 +32,6 @@ void EmitClangASTNodes(RecordKeeper &RK, raw_ostream &OS, const std::string &N, const std::string &S); -void EmitClangAttrParserStringSwitches(RecordKeeper &Records, raw_ostream &OS); void EmitClangAttrSubjectMatchRulesParserStringSwitches(RecordKeeper &Records, raw_ostream &OS); void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS); @@ -42,12 +41,10 @@ void EmitClangAttrPCHRead(RecordKeeper &Records, raw_ostream &OS); void EmitClangAttrPCHWrite(RecordKeeper &Records, raw_ostream &OS); void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS); -void EmitClangAttrSpellingListIndex(RecordKeeper &Records, raw_ostream &OS); void EmitClangAttrASTVisitor(RecordKeeper &Records, raw_ostream &OS); void EmitClangAttrTemplateInstantiate(RecordKeeper &Records, raw_ostream &OS); void EmitClangAttrParsedAttrList(RecordKeeper &Records, raw_ostream &OS); void EmitClangAttrParsedAttrImpl(RecordKeeper &Records, raw_ostream &OS); -void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS); void EmitClangAttrDump(RecordKeeper &Records, raw_ostream &OS); void EmitClangDiagsDefs(RecordKeeper &Records, raw_ostream &OS,