diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 474cf2c0e3f3..4c379620ab2d 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -935,7 +935,7 @@ class ASTContext : public RefCountedBase { /// \brief Get the additional modules in which the definition \p Def has /// been merged. - ArrayRef getModulesWithMergedDefinition(NamedDecl *Def) { + ArrayRef getModulesWithMergedDefinition(const NamedDecl *Def) { auto MergedIt = MergedDefModules.find(Def); if (MergedIt == MergedDefModules.end()) return None; @@ -2324,8 +2324,7 @@ class ASTContext : public RefCountedBase { uint64_t getTargetNullPointerValue(QualType QT) const; bool addressSpaceMapManglingFor(unsigned AS) const { - return AddrSpaceMapMangling || - AS >= LangAS::Count; + return AddrSpaceMapMangling || AS >= LangAS::FirstTargetAddressSpace; } private: diff --git a/include/clang/AST/CXXInheritance.h b/include/clang/AST/CXXInheritance.h index a7961ebe8ce6..980608570fd6 100644 --- a/include/clang/AST/CXXInheritance.h +++ b/include/clang/AST/CXXInheritance.h @@ -127,7 +127,11 @@ class CXXBasePaths { /// class subobjects for that class type. The key of the map is /// the cv-unqualified canonical type of the base class subobject. llvm::SmallDenseMap, 8> ClassSubobjects; - + + /// VisitedDependentRecords - Records the dependent records that have been + /// already visited. + llvm::SmallDenseSet VisitedDependentRecords; + /// FindAmbiguities - Whether Sema::IsDerivedFrom should try find /// ambiguous paths while it is looking for a path from a derived /// type to a base type. diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index 08879b36cce5..c26e2d7bde95 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -34,6 +34,7 @@ class DeclarationName; class DependentDiagnostic; class EnumDecl; class ExportDecl; +class ExternalSourceSymbolAttr; class FunctionDecl; class FunctionType; enum Linkage : unsigned char; @@ -332,15 +333,15 @@ class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) Decl { bool AccessDeclContextSanity() const; protected: - Decl(Kind DK, DeclContext *DC, SourceLocation L) - : NextInContextAndBits(), DeclCtx(DC), - Loc(L), DeclKind(DK), InvalidDecl(0), - HasAttrs(false), Implicit(false), Used(false), Referenced(false), - Access(AS_none), FromASTFile(0), Hidden(DC && cast(DC)->Hidden), - IdentifierNamespace(getIdentifierNamespaceForKind(DK)), - CacheValidAndLinkage(0) - { + : NextInContextAndBits(), DeclCtx(DC), Loc(L), DeclKind(DK), + InvalidDecl(0), HasAttrs(false), Implicit(false), Used(false), + Referenced(false), Access(AS_none), FromASTFile(0), + Hidden(DC && cast(DC)->Hidden && + (!cast(DC)->isFromASTFile() || + hasLocalOwningModuleStorage())), + IdentifierNamespace(getIdentifierNamespaceForKind(DK)), + CacheValidAndLinkage(0) { if (StatisticsEnabled) add(DK); } @@ -562,6 +563,10 @@ class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) Decl { NextInContextAndBits.setInt(Bits); } + /// \brief Looks on this and related declarations for an applicable + /// external source symbol attribute. + ExternalSourceSymbolAttr *getExternalSourceSymbolAttr() const; + /// \brief Whether this declaration was marked as being private to the /// module in which it was defined. bool isModulePrivate() const { @@ -698,6 +703,9 @@ class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) Decl { Module *getLocalOwningModule() const { if (isFromASTFile() || !Hidden) return nullptr; + + assert(hasLocalOwningModuleStorage() && + "hidden local decl but no local module storage"); return reinterpret_cast(this)[-1]; } void setLocalOwningModule(Module *M) { diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index b1c2503c32e3..9eb6d81296d8 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -333,15 +333,18 @@ class Qualifiers { bool hasAddressSpace() const { return Mask & AddressSpaceMask; } unsigned getAddressSpace() const { return Mask >> AddressSpaceShift; } + bool hasTargetSpecificAddressSpace() const { + return getAddressSpace() >= LangAS::FirstTargetAddressSpace; + } /// Get the address space attribute value to be printed by diagnostics. unsigned getAddressSpaceAttributePrintValue() const { auto Addr = getAddressSpace(); // This function is not supposed to be used with language specific // address spaces. If that happens, the diagnostic message should consider // printing the QualType instead of the address space value. - assert(Addr == 0 || Addr >= LangAS::Count); + assert(Addr == 0 || hasTargetSpecificAddressSpace()); if (Addr) - return Addr - LangAS::Count; + return Addr - LangAS::FirstTargetAddressSpace; // TODO: The diagnostic messages where Addr may be 0 should be fixed // since it cannot differentiate the situation where 0 denotes the default // address space or user specified __attribute__((address_space(0))). @@ -2008,10 +2011,11 @@ class Type : public ExtQualsTypeCommonBase { Optional getNullability(const ASTContext &context) const; /// Determine whether the given type can have a nullability - /// specifier applied to it, i.e., if it is any kind of pointer type - /// or a dependent type that could instantiate to any kind of - /// pointer type. - bool canHaveNullability() const; + /// specifier applied to it, i.e., if it is any kind of pointer type. + /// + /// \param ResultIfUnknown The value to return if we don't yet know whether + /// this type can have nullability because it is dependent. + bool canHaveNullability(bool ResultIfUnknown = true) const; /// Retrieve the set of substitutions required when accessing a member /// of the Objective-C receiver type that is declared in the given context. diff --git a/include/clang/Basic/AddressSpaces.h b/include/clang/Basic/AddressSpaces.h index 0ec5aafd64b6..95b9b9c7d0b3 100644 --- a/include/clang/Basic/AddressSpaces.h +++ b/include/clang/Basic/AddressSpaces.h @@ -45,13 +45,12 @@ enum ID { // This denotes the count of language-specific address spaces and also // the offset added to the target-specific address spaces, which are usually // specified by address space attributes __attribute__(address_space(n))). - Count + FirstTargetAddressSpace }; /// The type of a lookup table which maps from language-specific address spaces /// to target-specific ones. -typedef unsigned Map[Count]; - +typedef unsigned Map[FirstTargetAddressSpace]; } } diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index 4eb958e3f4d5..a885ede8df12 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -1179,6 +1179,12 @@ def MipsInterrupt : InheritableAttr, TargetSpecificAttr { let Documentation = [MipsInterruptDocs]; } +def MicroMips : InheritableAttr, TargetSpecificAttr { + let Spellings = [GCC<"micromips">]; + let Subjects = SubjectList<[Function], ErrorDiag>; + let Documentation = [MicroMipsDocs]; +} + def Mode : Attr { let Spellings = [GCC<"mode">]; let Subjects = SubjectList<[Var, Enum, TypedefName, Field], ErrorDiag, @@ -1261,6 +1267,12 @@ def NoMips16 : InheritableAttr, TargetSpecificAttr { let Documentation = [Undocumented]; } +def NoMicroMips : InheritableAttr, TargetSpecificAttr { + let Spellings = [GCC<"nomicromips">]; + let Subjects = SubjectList<[Function], ErrorDiag>; + let Documentation = [MicroMipsDocs]; +} + // This is not a TargetSpecificAttr so that is silently accepted and // ignored on other targets as encouraged by the OpenCL spec. // diff --git a/include/clang/Basic/AttrDocs.td b/include/clang/Basic/AttrDocs.td index 9e2fdf4834aa..65dd7445ba26 100644 --- a/include/clang/Basic/AttrDocs.td +++ b/include/clang/Basic/AttrDocs.td @@ -1269,6 +1269,19 @@ The semantics are as follows: }]; } +def MicroMipsDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +Clang supports the GNU style ``__attribute__((micromips))`` and +``__attribute__((nomicromips))`` attributes on MIPS targets. These attributes +may be attached to a function definition and instructs the backend to generate +or not to generate microMIPS code for that function. + +These attributes override the `-mmicromips` and `-mno-micromips` options +on the command line. + }]; +} + def AVRInterruptDocs : Documentation { let Category = DocCatFunction; let Content = [{ diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 1db6704f6d1f..463d057d8fd0 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -2490,7 +2490,7 @@ def err_attribute_address_multiple_qualifiers : Error< def err_attribute_address_function_type : Error< "function type may not be qualified with an address space">; def err_as_qualified_auto_decl : Error< - "automatic variable qualified with an address space">; + "automatic variable qualified with an%select{| invalid}0 address space">; def err_arg_with_address_space : Error< "parameter may not be qualified with an address space">; def err_field_with_address_space : Error< diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h index ceaedf58574f..2513de70e721 100644 --- a/include/clang/Basic/LangOptions.h +++ b/include/clang/Basic/LangOptions.h @@ -168,7 +168,7 @@ class LangOptions : public LangOptionsBase { /// Do we need to track the owning module for a local declaration? bool trackLocalOwningModule() const { - return ModulesLocalVisibility; + return isCompilingModule() || ModulesLocalVisibility || ModulesTS; } bool isSignedOverflowDefined() const { diff --git a/include/clang/Format/Format.h b/include/clang/Format/Format.h index a963c6369aa9..2405f8319c61 100644 --- a/include/clang/Format/Format.h +++ b/include/clang/Format/Format.h @@ -1133,6 +1133,9 @@ struct FormatStyle { /// ``Foo `` instead of ``Foo``. bool ObjCSpaceBeforeProtocolList; + /// \brief The penalty for breaking around an assignment operator. + unsigned PenaltyBreakAssignment; + /// \brief The penalty for breaking a function call after ``call(``. unsigned PenaltyBreakBeforeFirstCallParameter; @@ -1420,6 +1423,8 @@ struct FormatStyle { ObjCBlockIndentWidth == R.ObjCBlockIndentWidth && ObjCSpaceAfterProperty == R.ObjCSpaceAfterProperty && ObjCSpaceBeforeProtocolList == R.ObjCSpaceBeforeProtocolList && + PenaltyBreakAssignment == + R.PenaltyBreakAssignment && PenaltyBreakBeforeFirstCallParameter == R.PenaltyBreakBeforeFirstCallParameter && PenaltyBreakComment == R.PenaltyBreakComment && diff --git a/include/clang/Lex/ModuleMap.h b/include/clang/Lex/ModuleMap.h index 0fd6abe2f7d0..b6eed23f4d32 100644 --- a/include/clang/Lex/ModuleMap.h +++ b/include/clang/Lex/ModuleMap.h @@ -507,16 +507,6 @@ class ModuleMap { /// false otherwise. bool resolveConflicts(Module *Mod, bool Complain); - /// \brief Infers the (sub)module based on the given source location and - /// source manager. - /// - /// \param Loc The location within the source that we are querying, along - /// with its source manager. - /// - /// \returns The module that owns this source location, or null if no - /// module owns this source location. - Module *inferModuleFromLocation(FullSourceLoc Loc); - /// \brief Sets the umbrella header of the given module to the given /// header. void setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader, diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index 114bf70ad59a..9f015eaa230b 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -1917,14 +1917,11 @@ class Preprocessor { /// into a module, or is outside any module, returns nullptr. Module *getModuleForLocation(SourceLocation Loc); - /// \brief Find the module that contains the specified location, either - /// directly or indirectly. - Module *getModuleContainingLocation(SourceLocation Loc); - /// \brief We want to produce a diagnostic at location IncLoc concerning a /// missing module import. /// /// \param IncLoc The location at which the missing import was detected. + /// \param M The desired module. /// \param MLoc A location within the desired module at which some desired /// effect occurred (eg, where a desired entity was declared). /// @@ -1932,6 +1929,7 @@ class Preprocessor { /// Null if no such file could be determined or if a #include is not /// appropriate. const FileEntry *getModuleHeaderToIncludeForDiagnostics(SourceLocation IncLoc, + Module *M, SourceLocation MLoc); private: diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index f5a7e02941a7..537796fa6465 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -304,8 +304,9 @@ class Parser : public CodeCompletionHandler { } /// ConsumeToken - Consume the current 'peek token' and lex the next one. - /// This does not work with special tokens: string literals, code completion - /// and balanced tokens must be handled using the specific consume methods. + /// This does not work with special tokens: string literals, code completion, + /// annotation tokens and balanced tokens must be handled using the specific + /// consume methods. /// Returns the location of the consumed token. SourceLocation ConsumeToken() { assert(!isTokenSpecial() && @@ -366,7 +367,7 @@ class Parser : public CodeCompletionHandler { /// isTokenSpecial - True if this token requires special consumption methods. bool isTokenSpecial() const { return isTokenStringLiteral() || isTokenParen() || isTokenBracket() || - isTokenBrace() || Tok.is(tok::code_completion); + isTokenBrace() || Tok.is(tok::code_completion) || Tok.isAnnotation(); } /// \brief Returns true if the current token is '=' or is a type of '='. @@ -397,9 +398,19 @@ class Parser : public CodeCompletionHandler { if (Tok.is(tok::code_completion)) return ConsumeCodeCompletionTok ? ConsumeCodeCompletionToken() : handleUnexpectedCodeCompletionToken(); + if (Tok.isAnnotation()) + return ConsumeAnnotationToken(); return ConsumeToken(); } + SourceLocation ConsumeAnnotationToken() { + assert(Tok.isAnnotation() && "wrong consume method"); + SourceLocation Loc = Tok.getLocation(); + PrevTokLocation = Tok.getAnnotationEndLoc(); + PP.Lex(Tok); + return Loc; + } + /// ConsumeParen - This consume method keeps the paren count up-to-date. /// SourceLocation ConsumeParen() { @@ -1449,6 +1460,7 @@ class Parser : public CodeCompletionHandler { }; ExprResult ParseExpression(TypeCastState isTypeCast = NotTypeCast); + ExprResult ParseConstantExpressionInExprEvalContext(TypeCastState isTypeCast); ExprResult ParseConstantExpression(TypeCastState isTypeCast = NotTypeCast); ExprResult ParseConstraintExpression(); // Expr that doesn't include commas. diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h index df5e1050367e..bc817150ab82 100644 --- a/include/clang/Sema/DeclSpec.h +++ b/include/clang/Sema/DeclSpec.h @@ -1999,41 +1999,6 @@ class Declarator { llvm_unreachable("unknown context kind!"); } - /// diagnoseIdentifier - Return true if the identifier is prohibited and - /// should be diagnosed (because it cannot be anything else). - bool diagnoseIdentifier() const { - switch (Context) { - case FileContext: - case KNRTypeListContext: - case MemberContext: - case BlockContext: - case ForContext: - case InitStmtContext: - case ConditionContext: - case PrototypeContext: - case LambdaExprParameterContext: - case TemplateParamContext: - case CXXCatchContext: - case ObjCCatchContext: - case TypeNameContext: - case FunctionalCastContext: - case ConversionIdContext: - case ObjCParameterContext: - case ObjCResultContext: - case BlockLiteralContext: - case CXXNewContext: - case LambdaExprContext: - return false; - - case AliasDeclContext: - case AliasTemplateContext: - case TemplateTypeArgContext: - case TrailingReturnContext: - return true; - } - llvm_unreachable("unknown context kind!"); - } - /// Return true if the context permits a C++17 decomposition declarator. bool mayHaveDecompositionDeclarator() const { switch (Context) { diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index ba2da92c5be1..fcd3ee714fae 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -1507,6 +1507,12 @@ class Sema { hasVisibleDefaultArgument(const NamedDecl *D, llvm::SmallVectorImpl *Modules = nullptr); + /// Determine if there is a visible declaration of \p D that is an explicit + /// specialization declaration for a specialization of a template. (For a + /// member specialization, use hasVisibleMemberSpecialization.) + bool hasVisibleExplicitSpecialization( + const NamedDecl *D, llvm::SmallVectorImpl *Modules = nullptr); + /// Determine if there is a visible declaration of \p D that is a member /// specialization declaration (as opposed to an instantiated declaration). bool hasVisibleMemberSpecialization( @@ -2360,7 +2366,7 @@ class Sema { void MergeVarDeclTypes(VarDecl *New, VarDecl *Old, bool MergeTypeWithOld); void MergeVarDeclExceptionSpecs(VarDecl *New, VarDecl *Old); bool checkVarDeclRedefinition(VarDecl *OldDefn, VarDecl *NewDefn); - void notePreviousDefinition(SourceLocation Old, SourceLocation New); + void notePreviousDefinition(const NamedDecl *Old, SourceLocation New); bool MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, Scope *S); // AssignmentAction - This is used by all the assignment diagnostic functions @@ -7377,9 +7383,9 @@ class Sema { /// but have not yet been performed. std::deque PendingInstantiations; - class SavePendingInstantiationsAndVTableUsesRAII { + class GlobalEagerInstantiationScope { public: - SavePendingInstantiationsAndVTableUsesRAII(Sema &S, bool Enabled) + GlobalEagerInstantiationScope(Sema &S, bool Enabled) : S(S), Enabled(Enabled) { if (!Enabled) return; @@ -7387,7 +7393,14 @@ class Sema { SavedVTableUses.swap(S.VTableUses); } - ~SavePendingInstantiationsAndVTableUsesRAII() { + void perform() { + if (Enabled) { + S.DefineUsedVTables(); + S.PerformPendingInstantiations(); + } + } + + ~GlobalEagerInstantiationScope() { if (!Enabled) return; // Restore the set of pending vtables. @@ -7417,14 +7430,16 @@ class Sema { /// types, static variables, enumerators, etc. std::deque PendingLocalImplicitInstantiations; - class SavePendingLocalImplicitInstantiationsRAII { + class LocalEagerInstantiationScope { public: - SavePendingLocalImplicitInstantiationsRAII(Sema &S): S(S) { + LocalEagerInstantiationScope(Sema &S) : S(S) { SavedPendingLocalImplicitInstantiations.swap( S.PendingLocalImplicitInstantiations); } - ~SavePendingLocalImplicitInstantiationsRAII() { + void perform() { S.PerformPendingInstantiations(/*LocalOnly=*/true); } + + ~LocalEagerInstantiationScope() { assert(S.PendingLocalImplicitInstantiations.empty() && "there shouldn't be any pending local implicit instantiations"); SavedPendingLocalImplicitInstantiations.swap( @@ -7434,7 +7449,7 @@ class Sema { private: Sema &S; std::deque - SavedPendingLocalImplicitInstantiations; + SavedPendingLocalImplicitInstantiations; }; /// A helper class for building up ExtParameterInfos. diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h index 63ccb2461616..737f6fb3d413 100644 --- a/include/clang/Serialization/ASTReader.h +++ b/include/clang/Serialization/ASTReader.h @@ -478,10 +478,18 @@ class ASTReader /// in the chain. DeclUpdateOffsetsMap DeclUpdateOffsets; + struct PendingUpdateRecord { + Decl *D; + serialization::GlobalDeclID ID; + // Whether the declaration was just deserialized. + bool JustLoaded; + PendingUpdateRecord(serialization::GlobalDeclID ID, Decl *D, + bool JustLoaded) + : D(D), ID(ID), JustLoaded(JustLoaded) {} + }; /// \brief Declaration updates for already-loaded declarations that we need /// to apply once we finish processing an import. - llvm::SmallVector, 16> - PendingUpdateRecords; + llvm::SmallVector PendingUpdateRecords; enum class PendingFakeDefinitionKind { NotFake, Fake, FakeLoaded }; @@ -1279,7 +1287,7 @@ class ASTReader RecordLocation DeclCursorForID(serialization::DeclID ID, SourceLocation &Location); - void loadDeclUpdateRecords(serialization::DeclID ID, Decl *D); + void loadDeclUpdateRecords(PendingUpdateRecord &Record); void loadPendingDeclChain(Decl *D, uint64_t LocalOffset); void loadObjCCategories(serialization::GlobalDeclID ID, ObjCInterfaceDecl *D, unsigned PreviousGeneration = 0); diff --git a/include/clang/Serialization/ASTWriter.h b/include/clang/Serialization/ASTWriter.h index 17cf726e4d6b..f14dfc73baa9 100644 --- a/include/clang/Serialization/ASTWriter.h +++ b/include/clang/Serialization/ASTWriter.h @@ -627,10 +627,6 @@ class ASTWriter : public ASTDeserializationListener, /// \brief Add a version tuple to the given record void AddVersionTuple(const VersionTuple &Version, RecordDataImpl &Record); - /// \brief Infer the submodule ID that contains an entity at the given - /// source location. - serialization::SubmoduleID inferSubmoduleIDFromLocation(SourceLocation Loc); - /// \brief Retrieve or create a submodule ID for this module, or return 0 if /// the submodule is neither local (a submodle of the currently-written module) /// nor from an imported module. diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 3b526a23edd9..29d970e66d71 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -8730,8 +8730,8 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context, char *End; unsigned AddrSpace = strtoul(Str, &End, 10); if (End != Str && AddrSpace != 0) { - Type = Context.getAddrSpaceQualType(Type, AddrSpace + - LangAS::Count); + Type = Context.getAddrSpaceQualType( + Type, AddrSpace + LangAS::FirstTargetAddressSpace); Str = End; } if (c == '*') @@ -9546,13 +9546,8 @@ uint64_t ASTContext::getTargetNullPointerValue(QualType QT) const { } unsigned ASTContext::getTargetAddressSpace(unsigned AS) const { - // For OpenCL, only function local variables are not explicitly marked with - // an address space in the AST, and these need to be the address space of - // alloca. - if (!AS && LangOpts.OpenCL) - return getTargetInfo().getDataLayout().getAllocaAddrSpace(); - if (AS >= LangAS::Count) - return AS - LangAS::Count; + if (AS >= LangAS::FirstTargetAddressSpace) + return AS - LangAS::FirstTargetAddressSpace; else return (*AddrSpaceMap)[AS]; } diff --git a/lib/AST/CXXInheritance.cpp b/lib/AST/CXXInheritance.cpp index 746602d47be5..fc4d8b137337 100644 --- a/lib/AST/CXXInheritance.cpp +++ b/lib/AST/CXXInheritance.cpp @@ -57,6 +57,7 @@ bool CXXBasePaths::isAmbiguous(CanQualType BaseType) { void CXXBasePaths::clear() { Paths.clear(); ClassSubobjects.clear(); + VisitedDependentRecords.clear(); ScratchPath.clear(); DetectedVirtual = nullptr; } @@ -67,6 +68,7 @@ void CXXBasePaths::swap(CXXBasePaths &Other) { std::swap(Origin, Other.Origin); Paths.swap(Other.Paths); ClassSubobjects.swap(Other.ClassSubobjects); + VisitedDependentRecords.swap(Other.VisitedDependentRecords); std::swap(FindAmbiguities, Other.FindAmbiguities); std::swap(RecordPaths, Other.RecordPaths); std::swap(DetectVirtual, Other.DetectVirtual); @@ -278,8 +280,14 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context, dyn_cast_or_null(TN.getAsTemplateDecl())) BaseRecord = TD->getTemplatedDecl(); } - if (BaseRecord && !BaseRecord->hasDefinition()) - BaseRecord = nullptr; + if (BaseRecord) { + if (!BaseRecord->hasDefinition() || + VisitedDependentRecords.count(BaseRecord)) { + BaseRecord = nullptr; + } else { + VisitedDependentRecords.insert(BaseRecord); + } + } } else { BaseRecord = cast( BaseSpec.getType()->castAs()->getDecl()); diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index f6f81692611d..81cd1cc42658 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -407,6 +407,27 @@ bool Decl::isExported() const { return false; } +ExternalSourceSymbolAttr *Decl::getExternalSourceSymbolAttr() const { + const Decl *Definition = nullptr; + if (auto ID = dyn_cast(this)) { + Definition = ID->getDefinition(); + } else if (auto PD = dyn_cast(this)) { + Definition = PD->getDefinition(); + } else if (auto TD = dyn_cast(this)) { + Definition = TD->getDefinition(); + } + if (!Definition) + Definition = this; + + if (auto *attr = Definition->getAttr()) + return attr; + if (auto *dcd = dyn_cast(getDeclContext())) { + return dcd->getAttr(); + } + + return nullptr; +} + bool Decl::hasDefiningAttr() const { return hasAttr() || hasAttr(); } diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 75bb0cac51b8..bd8b3abd9275 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -4579,7 +4579,7 @@ class ExprEvaluatorBase } bool handleCallExpr(const CallExpr *E, APValue &Result, - const LValue *ResultSlot) { + const LValue *ResultSlot) { const Expr *Callee = E->getCallee()->IgnoreParens(); QualType CalleeType = Callee->getType(); @@ -4588,6 +4588,23 @@ class ExprEvaluatorBase auto Args = llvm::makeArrayRef(E->getArgs(), E->getNumArgs()); bool HasQualifier = false; + struct EvaluateIgnoredRAII { + public: + EvaluateIgnoredRAII(EvalInfo &Info, llvm::ArrayRef ToEval) + : Info(Info), ToEval(ToEval) {} + ~EvaluateIgnoredRAII() { + if (Info.noteFailure()) { + for (auto E : ToEval) + EvaluateIgnoredValue(Info, E); + } + } + void cancel() { ToEval = {}; } + void drop_front() { ToEval = ToEval.drop_front(); } + private: + EvalInfo &Info; + llvm::ArrayRef ToEval; + } EvalArguments(Info, Args); + // Extract function decl and 'this' pointer from the callee. if (CalleeType->isSpecificBuiltinType(BuiltinType::BoundMember)) { const ValueDecl *Member = nullptr; @@ -4637,10 +4654,12 @@ class ExprEvaluatorBase if (Args.empty()) return Error(E); - if (!EvaluateObjectArgument(Info, Args[0], ThisVal)) + const Expr *FirstArg = Args[0]; + Args = Args.drop_front(); + EvalArguments.drop_front(); + if (!EvaluateObjectArgument(Info, FirstArg, ThisVal)) return false; This = &ThisVal; - Args = Args.slice(1); } else if (MD && MD->isLambdaStaticInvoker()) { // Map the static invoker for the lambda back to the call operator. // Conveniently, we don't have to slice out the 'this' argument (as is @@ -4692,8 +4711,12 @@ class ExprEvaluatorBase const FunctionDecl *Definition = nullptr; Stmt *Body = FD->getBody(Definition); - if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body) || - !HandleFunctionCall(E->getExprLoc(), Definition, This, Args, Body, Info, + if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body)) + return false; + + EvalArguments.cancel(); + + if (!HandleFunctionCall(E->getExprLoc(), Definition, This, Args, Body, Info, Result, ResultSlot)) return false; diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 22d52bcd3f31..1e10094aeeea 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -3531,7 +3531,7 @@ Optional Type::getNullability(const ASTContext &context) const } while (true); } -bool Type::canHaveNullability() const { +bool Type::canHaveNullability(bool ResultIfUnknown) const { QualType type = getCanonicalTypeInternal(); switch (type->getTypeClass()) { @@ -3559,7 +3559,8 @@ bool Type::canHaveNullability() const { case Type::SubstTemplateTypeParmPack: case Type::DependentName: case Type::DependentTemplateSpecialization: - return true; + case Type::Auto: + return ResultIfUnknown; // Dependent template specializations can instantiate to pointer // types unless they're known to be specializations of a class @@ -3571,12 +3572,7 @@ bool Type::canHaveNullability() const { if (isa(templateDecl)) return false; } - return true; - - // auto is considered dependent when it isn't deduced. - case Type::Auto: - case Type::DeducedTemplateSpecialization: - return !cast(type.getTypePtr())->isDeduced(); + return ResultIfUnknown; case Type::Builtin: switch (cast(type.getTypePtr())->getKind()) { @@ -3595,7 +3591,7 @@ bool Type::canHaveNullability() const { case BuiltinType::PseudoObject: case BuiltinType::UnknownAny: case BuiltinType::ARCUnbridgedCast: - return true; + return ResultIfUnknown; case BuiltinType::Void: case BuiltinType::ObjCId: @@ -3614,6 +3610,7 @@ bool Type::canHaveNullability() const { case BuiltinType::OMPArraySection: return false; } + llvm_unreachable("unknown builtin type"); // Non-pointer types. case Type::Complex: @@ -3629,6 +3626,7 @@ bool Type::canHaveNullability() const { case Type::FunctionProto: case Type::FunctionNoProto: case Type::Record: + case Type::DeducedTemplateSpecialization: case Type::Enum: case Type::InjectedClassName: case Type::PackExpansion: diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp index 2be14ab62123..0551340c37a1 100644 --- a/lib/AST/TypePrinter.cpp +++ b/lib/AST/TypePrinter.cpp @@ -1668,9 +1668,9 @@ void Qualifiers::print(raw_ostream &OS, const PrintingPolicy& Policy, OS << "__shared"; break; default: - assert(addrspace >= LangAS::Count); + assert(addrspace >= LangAS::FirstTargetAddressSpace); OS << "__attribute__((address_space("; - OS << addrspace - LangAS::Count; + OS << addrspace - LangAS::FirstTargetAddressSpace; OS << ")))"; } } diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp index 92c561aa9413..1b9fbed17731 100644 --- a/lib/Basic/Targets.cpp +++ b/lib/Basic/Targets.cpp @@ -2034,25 +2034,45 @@ ArrayRef NVPTXTargetInfo::getGCCRegNames() const { return llvm::makeArrayRef(GCCRegNames); } -static const LangAS::Map AMDGPUPrivateIsZeroMap = { - 4, // Default - 1, // opencl_global - 3, // opencl_local - 2, // opencl_constant - 4, // opencl_generic - 1, // cuda_device - 2, // cuda_constant - 3 // cuda_shared +static const LangAS::Map AMDGPUNonOpenCLPrivateIsZeroMap = { + 4, // Default + 1, // opencl_global + 3, // opencl_local + 2, // opencl_constant + 4, // opencl_generic + 1, // cuda_device + 2, // cuda_constant + 3 // cuda_shared }; -static const LangAS::Map AMDGPUGenericIsZeroMap = { - 0, // Default - 1, // opencl_global - 3, // opencl_local - 2, // opencl_constant - 0, // opencl_generic - 1, // cuda_device - 2, // cuda_constant - 3 // cuda_shared +static const LangAS::Map AMDGPUNonOpenCLGenericIsZeroMap = { + 0, // Default + 1, // opencl_global + 3, // opencl_local + 2, // opencl_constant + 0, // opencl_generic + 1, // cuda_device + 2, // cuda_constant + 3 // cuda_shared +}; +static const LangAS::Map AMDGPUOpenCLPrivateIsZeroMap = { + 0, // Default + 1, // opencl_global + 3, // opencl_local + 2, // opencl_constant + 4, // opencl_generic + 1, // cuda_device + 2, // cuda_constant + 3 // cuda_shared +}; +static const LangAS::Map AMDGPUOpenCLGenericIsZeroMap = { + 5, // Default + 1, // opencl_global + 3, // opencl_local + 2, // opencl_constant + 0, // opencl_generic + 1, // cuda_device + 2, // cuda_constant + 3 // cuda_shared }; // If you edit the description strings, make sure you update @@ -2149,8 +2169,12 @@ class AMDGPUTargetInfo final : public TargetInfo { : DataLayoutStringR600); assert(DataLayout->getAllocaAddrSpace() == AS.Private); - AddrSpaceMap = IsGenericZero ? &AMDGPUGenericIsZeroMap : - &AMDGPUPrivateIsZeroMap; + AddrSpaceMap = + llvm::StringSwitch(Triple.getEnvironmentName()) + .Case("opencl", &AMDGPUOpenCLPrivateIsZeroMap) + .Case("amdgiz", &AMDGPUNonOpenCLGenericIsZeroMap) + .Case("amdgizcl", &AMDGPUOpenCLGenericIsZeroMap) + .Default(&AMDGPUNonOpenCLPrivateIsZeroMap); UseAddrSpaceMapMangling = true; } diff --git a/lib/CodeGen/CGAtomic.cpp b/lib/CodeGen/CGAtomic.cpp index 28e20b53d656..a6e6fec206d5 100644 --- a/lib/CodeGen/CGAtomic.cpp +++ b/lib/CodeGen/CGAtomic.cpp @@ -95,7 +95,7 @@ namespace { BFI.StorageOffset += OffsetInChars; LVal = LValue::MakeBitfield(Address(Addr, lvalue.getAlignment()), BFI, lvalue.getType(), - lvalue.getAlignmentSource()); + lvalue.getBaseInfo()); LVal.setTBAAInfo(lvalue.getTBAAInfo()); AtomicTy = C.getIntTypeForBitwidth(AtomicSizeInBits, OrigBFI.IsSigned); if (AtomicTy.isNull()) { @@ -203,7 +203,7 @@ namespace { addr = CGF.Builder.CreateStructGEP(addr, 0, CharUnits()); return LValue::MakeAddr(addr, getValueType(), CGF.getContext(), - LVal.getAlignmentSource(), LVal.getTBAAInfo()); + LVal.getBaseInfo(), LVal.getTBAAInfo()); } /// \brief Emits atomic load. @@ -1181,15 +1181,15 @@ RValue AtomicInfo::convertAtomicTempToRValue(Address addr, if (LVal.isBitField()) return CGF.EmitLoadOfBitfieldLValue( LValue::MakeBitfield(addr, LVal.getBitFieldInfo(), LVal.getType(), - LVal.getAlignmentSource()), loc); + LVal.getBaseInfo()), loc); if (LVal.isVectorElt()) return CGF.EmitLoadOfLValue( LValue::MakeVectorElt(addr, LVal.getVectorIdx(), LVal.getType(), - LVal.getAlignmentSource()), loc); + LVal.getBaseInfo()), loc); assert(LVal.isExtVectorElt()); return CGF.EmitLoadOfExtVectorElementLValue(LValue::MakeExtVectorElt( addr, LVal.getExtVectorElts(), LVal.getType(), - LVal.getAlignmentSource())); + LVal.getBaseInfo())); } RValue AtomicInfo::ConvertIntToValueOrAtomic(llvm::Value *IntVal, @@ -1506,26 +1506,26 @@ EmitAtomicUpdateValue(CodeGenFunction &CGF, AtomicInfo &Atomics, RValue OldRVal, UpdateLVal = LValue::MakeBitfield(Ptr, AtomicLVal.getBitFieldInfo(), AtomicLVal.getType(), - AtomicLVal.getAlignmentSource()); + AtomicLVal.getBaseInfo()); DesiredLVal = LValue::MakeBitfield(DesiredAddr, AtomicLVal.getBitFieldInfo(), AtomicLVal.getType(), - AtomicLVal.getAlignmentSource()); + AtomicLVal.getBaseInfo()); } else if (AtomicLVal.isVectorElt()) { UpdateLVal = LValue::MakeVectorElt(Ptr, AtomicLVal.getVectorIdx(), AtomicLVal.getType(), - AtomicLVal.getAlignmentSource()); + AtomicLVal.getBaseInfo()); DesiredLVal = LValue::MakeVectorElt( DesiredAddr, AtomicLVal.getVectorIdx(), AtomicLVal.getType(), - AtomicLVal.getAlignmentSource()); + AtomicLVal.getBaseInfo()); } else { assert(AtomicLVal.isExtVectorElt()); UpdateLVal = LValue::MakeExtVectorElt(Ptr, AtomicLVal.getExtVectorElts(), AtomicLVal.getType(), - AtomicLVal.getAlignmentSource()); + AtomicLVal.getBaseInfo()); DesiredLVal = LValue::MakeExtVectorElt( DesiredAddr, AtomicLVal.getExtVectorElts(), AtomicLVal.getType(), - AtomicLVal.getAlignmentSource()); + AtomicLVal.getBaseInfo()); } UpdateLVal.setTBAAInfo(AtomicLVal.getTBAAInfo()); DesiredLVal.setTBAAInfo(AtomicLVal.getTBAAInfo()); @@ -1612,17 +1612,17 @@ static void EmitAtomicUpdateValue(CodeGenFunction &CGF, AtomicInfo &Atomics, DesiredLVal = LValue::MakeBitfield(DesiredAddr, AtomicLVal.getBitFieldInfo(), AtomicLVal.getType(), - AtomicLVal.getAlignmentSource()); + AtomicLVal.getBaseInfo()); } else if (AtomicLVal.isVectorElt()) { DesiredLVal = LValue::MakeVectorElt(DesiredAddr, AtomicLVal.getVectorIdx(), AtomicLVal.getType(), - AtomicLVal.getAlignmentSource()); + AtomicLVal.getBaseInfo()); } else { assert(AtomicLVal.isExtVectorElt()); DesiredLVal = LValue::MakeExtVectorElt( DesiredAddr, AtomicLVal.getExtVectorElts(), AtomicLVal.getType(), - AtomicLVal.getAlignmentSource()); + AtomicLVal.getBaseInfo()); } DesiredLVal.setTBAAInfo(AtomicLVal.getTBAAInfo()); // Store new value in the corresponding memory area diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp index f1c20e9df1f3..2e423b25f0fb 100644 --- a/lib/CodeGen/CGBlocks.cpp +++ b/lib/CodeGen/CGBlocks.cpp @@ -918,8 +918,9 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) { // FIXME: Pass a specific location for the expr init so that the store is // attributed to a reasonable location - otherwise it may be attributed to // locations of subexpressions in the initialization. + LValueBaseInfo BaseInfo(AlignmentSource::Decl, false); EmitExprAsInit(&l2r, &blockFieldPseudoVar, - MakeAddrLValue(blockField, type, AlignmentSource::Decl), + MakeAddrLValue(blockField, type, BaseInfo), /*captured by init*/ false); } diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 50c9e22801c7..e2d5f8f870de 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -8842,9 +8842,8 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID, const CallExpr *E) { auto MakeLdg = [&](unsigned IntrinsicID) { Value *Ptr = EmitScalarExpr(E->getArg(0)); - AlignmentSource AlignSource; clang::CharUnits Align = - getNaturalPointeeTypeAlignment(E->getArg(0)->getType(), &AlignSource); + getNaturalPointeeTypeAlignment(E->getArg(0)->getType()); return Builder.CreateCall( CGM.getIntrinsic(IntrinsicID, {Ptr->getType()->getPointerElementType(), Ptr->getType()}), diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp index 7ba03a0d42dd..5b4dc5ff0ab3 100644 --- a/lib/CodeGen/CGClass.cpp +++ b/lib/CodeGen/CGClass.cpp @@ -129,14 +129,14 @@ Address CodeGenFunction::EmitCXXMemberDataPointerAddress(const Expr *E, Address base, llvm::Value *memberPtr, const MemberPointerType *memberPtrType, - AlignmentSource *alignSource) { + LValueBaseInfo *BaseInfo) { // Ask the ABI to compute the actual address. llvm::Value *ptr = CGM.getCXXABI().EmitMemberDataPointerAddress(*this, E, base, memberPtr, memberPtrType); QualType memberType = memberPtrType->getPointeeType(); - CharUnits memberAlign = getNaturalTypeAlignment(memberType, alignSource); + CharUnits memberAlign = getNaturalTypeAlignment(memberType, BaseInfo); memberAlign = CGM.getDynamicOffsetAlignment(base.getAlignment(), memberPtrType->getClass()->getAsCXXRecordDecl(), diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index bf178dd7fd80..0a1dc09211c2 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -2613,7 +2613,7 @@ llvm::DIModule *CGDebugInfo::getParentModuleOrNull(const Decl *D) { // best to make this behavior a command line or debugger tuning // option. FullSourceLoc Loc(D->getLocation(), CGM.getContext().getSourceManager()); - if (Module *M = ClangModuleMap->inferModuleFromLocation(Loc)) { + if (Module *M = D->getOwningModule()) { // This is a (sub-)module. auto Info = ExternalASTSource::ASTSourceDescriptor(*M); return getOrCreateModuleRef(Info, /*SkeletonCU=*/false); diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index 0fa8eeb1c3e1..d6abfa15e541 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -11,14 +11,15 @@ // //===----------------------------------------------------------------------===// -#include "CodeGenFunction.h" #include "CGBlocks.h" #include "CGCXXABI.h" #include "CGCleanup.h" #include "CGDebugInfo.h" #include "CGOpenCLRuntime.h" #include "CGOpenMPRuntime.h" +#include "CodeGenFunction.h" #include "CodeGenModule.h" +#include "TargetInfo.h" #include "clang/AST/ASTContext.h" #include "clang/AST/CharUnits.h" #include "clang/AST/Decl.h" @@ -1105,6 +1106,21 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) { address = Address(vla, alignment); } + // Alloca always returns a pointer in alloca address space, which may + // be different from the type defined by the language. For example, + // in C++ the auto variables are in the default address space. Therefore + // cast alloca to the expected address space when necessary. + auto T = D.getType(); + assert(T.getAddressSpace() == LangAS::Default); + if (getASTAllocaAddressSpace() != LangAS::Default) { + auto *Addr = getTargetHooks().performAddrSpaceCast( + *this, address.getPointer(), getASTAllocaAddressSpace(), + T.getAddressSpace(), + address.getElementType()->getPointerTo( + getContext().getTargetAddressSpace(T.getAddressSpace())), + /*non-null*/ true); + address = Address(Addr, address.getAlignment()); + } setAddrOfLocalVar(&D, address); emission.Addr = address; diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index cef6292c0e4d..a6d5dd85c234 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -374,12 +374,14 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) { // dynamic initialization or a cleanup and we can just return the address // of the temporary. if (Var->hasInitializer()) - return MakeAddrLValue(Object, M->getType(), AlignmentSource::Decl); + return MakeAddrLValue(Object, M->getType(), + LValueBaseInfo(AlignmentSource::Decl, false)); Var->setInitializer(CGM.EmitNullConstant(E->getType())); } LValue RefTempDst = MakeAddrLValue(Object, M->getType(), - AlignmentSource::Decl); + LValueBaseInfo(AlignmentSource::Decl, + false)); switch (getEvaluationKind(E->getType())) { default: llvm_unreachable("expected scalar or aggregate expression"); @@ -465,7 +467,7 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) { case SubobjectAdjustment::FieldAdjustment: { LValue LV = MakeAddrLValue(Object, E->getType(), - AlignmentSource::Decl); + LValueBaseInfo(AlignmentSource::Decl, false)); LV = EmitLValueForField(LV, Adjustment.Field); assert(LV.isSimple() && "materialized temporary field is not a simple lvalue"); @@ -482,7 +484,8 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) { } } - return MakeAddrLValue(Object, M->getType(), AlignmentSource::Decl); + return MakeAddrLValue(Object, M->getType(), + LValueBaseInfo(AlignmentSource::Decl, false)); } RValue @@ -847,7 +850,7 @@ void CodeGenModule::EmitExplicitCastExprType(const ExplicitCastExpr *E, /// EmitPointerWithAlignment - Given an expression of pointer type, try to /// derive a more accurate bound on the alignment of the pointer. Address CodeGenFunction::EmitPointerWithAlignment(const Expr *E, - AlignmentSource *Source) { + LValueBaseInfo *BaseInfo) { // We allow this with ObjC object pointers because of fragile ABIs. assert(E->getType()->isPointerType() || E->getType()->isObjCObjectPointerType()); @@ -866,16 +869,20 @@ Address CodeGenFunction::EmitPointerWithAlignment(const Expr *E, if (PtrTy->getPointeeType()->isVoidType()) break; - AlignmentSource InnerSource; - Address Addr = EmitPointerWithAlignment(CE->getSubExpr(), &InnerSource); - if (Source) *Source = InnerSource; + LValueBaseInfo InnerInfo; + Address Addr = EmitPointerWithAlignment(CE->getSubExpr(), &InnerInfo); + if (BaseInfo) *BaseInfo = InnerInfo; // If this is an explicit bitcast, and the source l-value is // opaque, honor the alignment of the casted-to type. if (isa(CE) && - InnerSource != AlignmentSource::Decl) { - Addr = Address(Addr.getPointer(), - getNaturalPointeeTypeAlignment(E->getType(), Source)); + InnerInfo.getAlignmentSource() != AlignmentSource::Decl) { + LValueBaseInfo ExpInfo; + CharUnits Align = getNaturalPointeeTypeAlignment(E->getType(), + &ExpInfo); + if (BaseInfo) + BaseInfo->mergeForCast(ExpInfo); + Addr = Address(Addr.getPointer(), Align); } if (SanOpts.has(SanitizerKind::CFIUnrelatedCast) && @@ -893,12 +900,12 @@ Address CodeGenFunction::EmitPointerWithAlignment(const Expr *E, // Array-to-pointer decay. case CK_ArrayToPointerDecay: - return EmitArrayToPointerDecay(CE->getSubExpr(), Source); + return EmitArrayToPointerDecay(CE->getSubExpr(), BaseInfo); // Derived-to-base conversions. case CK_UncheckedDerivedToBase: case CK_DerivedToBase: { - Address Addr = EmitPointerWithAlignment(CE->getSubExpr(), Source); + Address Addr = EmitPointerWithAlignment(CE->getSubExpr(), BaseInfo); auto Derived = CE->getSubExpr()->getType()->getPointeeCXXRecordDecl(); return GetAddressOfBaseClass(Addr, Derived, CE->path_begin(), CE->path_end(), @@ -917,7 +924,7 @@ Address CodeGenFunction::EmitPointerWithAlignment(const Expr *E, if (const UnaryOperator *UO = dyn_cast(E)) { if (UO->getOpcode() == UO_AddrOf) { LValue LV = EmitLValue(UO->getSubExpr()); - if (Source) *Source = LV.getAlignmentSource(); + if (BaseInfo) *BaseInfo = LV.getBaseInfo(); return LV.getAddress(); } } @@ -925,7 +932,7 @@ Address CodeGenFunction::EmitPointerWithAlignment(const Expr *E, // TODO: conditional operators, comma. // Otherwise, use the alignment of the type. - CharUnits Align = getNaturalPointeeTypeAlignment(E->getType(), Source); + CharUnits Align = getNaturalPointeeTypeAlignment(E->getType(), BaseInfo); return Address(EmitScalarExpr(E), Align); } @@ -1094,7 +1101,7 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) { llvm::Value *V = LV.getPointer(); Scope.ForceCleanup({&V}); return LValue::MakeAddr(Address(V, LV.getAlignment()), LV.getType(), - getContext(), LV.getAlignmentSource(), + getContext(), LV.getBaseInfo(), LV.getTBAAInfo()); } // FIXME: Is it possible to create an ExprWithCleanups that produces a @@ -1269,7 +1276,7 @@ CodeGenFunction::tryEmitAsConstant(DeclRefExpr *refExpr) { llvm::Value *CodeGenFunction::EmitLoadOfScalar(LValue lvalue, SourceLocation Loc) { return EmitLoadOfScalar(lvalue.getAddress(), lvalue.isVolatile(), - lvalue.getType(), Loc, lvalue.getAlignmentSource(), + lvalue.getType(), Loc, lvalue.getBaseInfo(), lvalue.getTBAAInfo(), lvalue.getTBAABaseType(), lvalue.getTBAAOffset(), lvalue.isNontemporal()); @@ -1381,7 +1388,7 @@ bool CodeGenFunction::EmitScalarRangeCheck(llvm::Value *Value, QualType Ty, llvm::Value *CodeGenFunction::EmitLoadOfScalar(Address Addr, bool Volatile, QualType Ty, SourceLocation Loc, - AlignmentSource AlignSource, + LValueBaseInfo BaseInfo, llvm::MDNode *TBAAInfo, QualType TBAABaseType, uint64_t TBAAOffset, @@ -1413,7 +1420,7 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(Address Addr, bool Volatile, // Atomic operations have to be done on integral types. LValue AtomicLValue = - LValue::MakeAddr(Addr, Ty, getContext(), AlignSource, TBAAInfo); + LValue::MakeAddr(Addr, Ty, getContext(), BaseInfo, TBAAInfo); if (Ty->isAtomicType() || LValueIsSuitableForInlineAtomic(AtomicLValue)) { return EmitAtomicLoad(AtomicLValue, Loc).getScalarVal(); } @@ -1469,7 +1476,7 @@ llvm::Value *CodeGenFunction::EmitFromMemory(llvm::Value *Value, QualType Ty) { void CodeGenFunction::EmitStoreOfScalar(llvm::Value *Value, Address Addr, bool Volatile, QualType Ty, - AlignmentSource AlignSource, + LValueBaseInfo BaseInfo, llvm::MDNode *TBAAInfo, bool isInit, QualType TBAABaseType, uint64_t TBAAOffset, @@ -1500,7 +1507,7 @@ void CodeGenFunction::EmitStoreOfScalar(llvm::Value *Value, Address Addr, Value = EmitToMemory(Value, Ty); LValue AtomicLValue = - LValue::MakeAddr(Addr, Ty, getContext(), AlignSource, TBAAInfo); + LValue::MakeAddr(Addr, Ty, getContext(), BaseInfo, TBAAInfo); if (Ty->isAtomicType() || (!isInit && LValueIsSuitableForInlineAtomic(AtomicLValue))) { EmitAtomicStore(RValue::get(Value), AtomicLValue, isInit); @@ -1526,7 +1533,7 @@ void CodeGenFunction::EmitStoreOfScalar(llvm::Value *Value, Address Addr, void CodeGenFunction::EmitStoreOfScalar(llvm::Value *value, LValue lvalue, bool isInit) { EmitStoreOfScalar(value, lvalue.getAddress(), lvalue.isVolatile(), - lvalue.getType(), lvalue.getAlignmentSource(), + lvalue.getType(), lvalue.getBaseInfo(), lvalue.getTBAAInfo(), isInit, lvalue.getTBAABaseType(), lvalue.getTBAAOffset(), lvalue.isNontemporal()); } @@ -2058,38 +2065,39 @@ static LValue EmitThreadPrivateVarDeclLValue( llvm::Type *RealVarTy, SourceLocation Loc) { Addr = CGF.CGM.getOpenMPRuntime().getAddrOfThreadPrivate(CGF, VD, Addr, Loc); Addr = CGF.Builder.CreateElementBitCast(Addr, RealVarTy); - return CGF.MakeAddrLValue(Addr, T, AlignmentSource::Decl); + LValueBaseInfo BaseInfo(AlignmentSource::Decl, false); + return CGF.MakeAddrLValue(Addr, T, BaseInfo); } Address CodeGenFunction::EmitLoadOfReference(Address Addr, const ReferenceType *RefTy, - AlignmentSource *Source) { + LValueBaseInfo *BaseInfo) { llvm::Value *Ptr = Builder.CreateLoad(Addr); return Address(Ptr, getNaturalTypeAlignment(RefTy->getPointeeType(), - Source, /*forPointee*/ true)); - + BaseInfo, /*forPointee*/ true)); } LValue CodeGenFunction::EmitLoadOfReferenceLValue(Address RefAddr, const ReferenceType *RefTy) { - AlignmentSource Source; - Address Addr = EmitLoadOfReference(RefAddr, RefTy, &Source); - return MakeAddrLValue(Addr, RefTy->getPointeeType(), Source); + LValueBaseInfo BaseInfo; + Address Addr = EmitLoadOfReference(RefAddr, RefTy, &BaseInfo); + return MakeAddrLValue(Addr, RefTy->getPointeeType(), BaseInfo); } Address CodeGenFunction::EmitLoadOfPointer(Address Ptr, const PointerType *PtrTy, - AlignmentSource *Source) { + LValueBaseInfo *BaseInfo) { llvm::Value *Addr = Builder.CreateLoad(Ptr); - return Address(Addr, getNaturalTypeAlignment(PtrTy->getPointeeType(), Source, + return Address(Addr, getNaturalTypeAlignment(PtrTy->getPointeeType(), + BaseInfo, /*forPointeeType=*/true)); } LValue CodeGenFunction::EmitLoadOfPointerLValue(Address PtrAddr, const PointerType *PtrTy) { - AlignmentSource Source; - Address Addr = EmitLoadOfPointer(PtrAddr, PtrTy, &Source); - return MakeAddrLValue(Addr, PtrTy->getPointeeType(), Source); + LValueBaseInfo BaseInfo; + Address Addr = EmitLoadOfPointer(PtrAddr, PtrTy, &BaseInfo); + return MakeAddrLValue(Addr, PtrTy->getPointeeType(), BaseInfo); } static LValue EmitGlobalVarDeclLValue(CodeGenFunction &CGF, @@ -2115,7 +2123,8 @@ static LValue EmitGlobalVarDeclLValue(CodeGenFunction &CGF, if (auto RefTy = VD->getType()->getAs()) { LV = CGF.EmitLoadOfReferenceLValue(Addr, RefTy); } else { - LV = CGF.MakeAddrLValue(Addr, T, AlignmentSource::Decl); + LValueBaseInfo BaseInfo(AlignmentSource::Decl, false); + LV = CGF.MakeAddrLValue(Addr, T, BaseInfo); } setObjCGCLValueClass(CGF.getContext(), E, LV); return LV; @@ -2149,7 +2158,8 @@ static LValue EmitFunctionDeclLValue(CodeGenFunction &CGF, const Expr *E, const FunctionDecl *FD) { llvm::Value *V = EmitFunctionDeclPointer(CGF.CGM, FD); CharUnits Alignment = CGF.getContext().getDeclAlign(FD); - return CGF.MakeAddrLValue(V, E->getType(), Alignment, AlignmentSource::Decl); + LValueBaseInfo BaseInfo(AlignmentSource::Decl, false); + return CGF.MakeAddrLValue(V, E->getType(), Alignment, BaseInfo); } static LValue EmitCapturedFieldLValue(CodeGenFunction &CGF, const FieldDecl *FD, @@ -2214,8 +2224,8 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { // Should we be using the alignment of the constant pointer we emitted? CharUnits Alignment = getNaturalTypeAlignment(E->getType(), nullptr, /*pointee*/ true); - - return MakeAddrLValue(Address(Val, Alignment), T, AlignmentSource::Decl); + LValueBaseInfo BaseInfo(AlignmentSource::Decl, false); + return MakeAddrLValue(Address(Val, Alignment), T, BaseInfo); } // Check for captured variables. @@ -2232,14 +2242,16 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { LValue CapLVal = EmitCapturedFieldLValue(*this, CapturedStmtInfo->lookup(VD), CapturedStmtInfo->getContextValue()); + bool MayAlias = CapLVal.getBaseInfo().getMayAlias(); return MakeAddrLValue( Address(CapLVal.getPointer(), getContext().getDeclAlign(VD)), - CapLVal.getType(), AlignmentSource::Decl); + CapLVal.getType(), LValueBaseInfo(AlignmentSource::Decl, MayAlias)); } assert(isa(CurCodeDecl)); Address addr = GetAddrOfBlockDecl(VD, VD->hasAttr()); - return MakeAddrLValue(addr, T, AlignmentSource::Decl); + LValueBaseInfo BaseInfo(AlignmentSource::Decl, false); + return MakeAddrLValue(addr, T, BaseInfo); } } @@ -2253,7 +2265,8 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { if (ND->hasAttr()) { const auto *VD = cast(ND); ConstantAddress Aliasee = CGM.GetWeakRefReference(VD); - return MakeAddrLValue(Aliasee, T, AlignmentSource::Decl); + return MakeAddrLValue(Aliasee, T, + LValueBaseInfo(AlignmentSource::Decl, false)); } if (const auto *VD = dyn_cast(ND)) { @@ -2299,7 +2312,8 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { if (auto RefTy = VD->getType()->getAs()) { LV = EmitLoadOfReferenceLValue(addr, RefTy); } else { - LV = MakeAddrLValue(addr, T, AlignmentSource::Decl); + LValueBaseInfo BaseInfo(AlignmentSource::Decl, false); + LV = MakeAddrLValue(addr, T, BaseInfo); } bool isLocalStorage = VD->hasLocalStorage(); @@ -2344,9 +2358,9 @@ LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) { QualType T = E->getSubExpr()->getType()->getPointeeType(); assert(!T.isNull() && "CodeGenFunction::EmitUnaryOpLValue: Illegal type"); - AlignmentSource AlignSource; - Address Addr = EmitPointerWithAlignment(E->getSubExpr(), &AlignSource); - LValue LV = MakeAddrLValue(Addr, T, AlignSource); + LValueBaseInfo BaseInfo; + Address Addr = EmitPointerWithAlignment(E->getSubExpr(), &BaseInfo); + LValue LV = MakeAddrLValue(Addr, T, BaseInfo); LV.getQuals().setAddressSpace(ExprTy.getAddressSpace()); // We should not generate __weak write barrier on indirect reference @@ -2378,7 +2392,7 @@ LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) { (E->getOpcode() == UO_Real ? emitAddrOfRealComponent(LV.getAddress(), LV.getType()) : emitAddrOfImagComponent(LV.getAddress(), LV.getType())); - LValue ElemLV = MakeAddrLValue(Component, T, LV.getAlignmentSource()); + LValue ElemLV = MakeAddrLValue(Component, T, LV.getBaseInfo()); ElemLV.getQuals().addQualifiers(LV.getQuals()); return ElemLV; } @@ -2398,12 +2412,14 @@ LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) { LValue CodeGenFunction::EmitStringLiteralLValue(const StringLiteral *E) { return MakeAddrLValue(CGM.GetAddrOfConstantStringFromLiteral(E), - E->getType(), AlignmentSource::Decl); + E->getType(), + LValueBaseInfo(AlignmentSource::Decl, false)); } LValue CodeGenFunction::EmitObjCEncodeExprLValue(const ObjCEncodeExpr *E) { return MakeAddrLValue(CGM.GetAddrOfConstantStringFromObjCEncode(E), - E->getType(), AlignmentSource::Decl); + E->getType(), + LValueBaseInfo(AlignmentSource::Decl, false)); } LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) { @@ -2415,6 +2431,7 @@ LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) { StringRef NameItems[] = { PredefinedExpr::getIdentTypeName(E->getIdentType()), FnName}; std::string GVName = llvm::join(NameItems, NameItems + 2, "."); + LValueBaseInfo BaseInfo(AlignmentSource::Decl, false); if (auto *BD = dyn_cast(CurCodeDecl)) { std::string Name = SL->getString(); if (!Name.empty()) { @@ -2423,14 +2440,14 @@ LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) { if (Discriminator) Name += "_" + Twine(Discriminator + 1).str(); auto C = CGM.GetAddrOfConstantCString(Name, GVName.c_str()); - return MakeAddrLValue(C, E->getType(), AlignmentSource::Decl); + return MakeAddrLValue(C, E->getType(), BaseInfo); } else { auto C = CGM.GetAddrOfConstantCString(FnName, GVName.c_str()); - return MakeAddrLValue(C, E->getType(), AlignmentSource::Decl); + return MakeAddrLValue(C, E->getType(), BaseInfo); } } auto C = CGM.GetAddrOfConstantStringFromLiteral(SL, GVName); - return MakeAddrLValue(C, E->getType(), AlignmentSource::Decl); + return MakeAddrLValue(C, E->getType(), BaseInfo); } /// Emit a type description suitable for use by a runtime sanitizer library. The @@ -2937,14 +2954,14 @@ llvm::CallInst *CodeGenFunction::EmitTrapCall(llvm::Intrinsic::ID IntrID) { } Address CodeGenFunction::EmitArrayToPointerDecay(const Expr *E, - AlignmentSource *AlignSource) { + LValueBaseInfo *BaseInfo) { assert(E->getType()->isArrayType() && "Array to pointer decay must have array source type!"); // Expressions of array type can't be bitfields or vector elements. LValue LV = EmitLValue(E); Address Addr = LV.getAddress(); - if (AlignSource) *AlignSource = LV.getAlignmentSource(); + if (BaseInfo) *BaseInfo = LV.getBaseInfo(); // If the array type was an incomplete type, we need to make sure // the decay ends up being the right type. @@ -3079,7 +3096,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, assert(LHS.isSimple() && "Can only subscript lvalue vectors here!"); return LValue::MakeVectorElt(LHS.getAddress(), Idx, E->getBase()->getType(), - LHS.getAlignmentSource()); + LHS.getBaseInfo()); } // All the other cases basically behave like simple offsetting. @@ -3092,17 +3109,17 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, QualType EltType = LV.getType()->castAs()->getElementType(); Addr = emitArraySubscriptGEP(*this, Addr, Idx, EltType, /*inbounds*/ true); - return MakeAddrLValue(Addr, EltType, LV.getAlignmentSource()); + return MakeAddrLValue(Addr, EltType, LV.getBaseInfo()); } - AlignmentSource AlignSource; + LValueBaseInfo BaseInfo; Address Addr = Address::invalid(); if (const VariableArrayType *vla = getContext().getAsVariableArrayType(E->getType())) { // The base must be a pointer, which is not an aggregate. Emit // it. It needs to be emitted first in case it's what captures // the VLA bounds. - Addr = EmitPointerWithAlignment(E->getBase(), &AlignSource); + Addr = EmitPointerWithAlignment(E->getBase(), &BaseInfo); auto *Idx = EmitIdxAfterBase(/*Promote*/true); // The element count here is the total number of non-VLA elements. @@ -3125,7 +3142,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, // Indexing over an interface, as in "NSString *P; P[4];" // Emit the base pointer. - Addr = EmitPointerWithAlignment(E->getBase(), &AlignSource); + Addr = EmitPointerWithAlignment(E->getBase(), &BaseInfo); auto *Idx = EmitIdxAfterBase(/*Promote*/true); CharUnits InterfaceSize = getContext().getTypeSizeInChars(OIT); @@ -3171,16 +3188,16 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, {CGM.getSize(CharUnits::Zero()), Idx}, E->getType(), !getLangOpts().isSignedOverflowDefined()); - AlignSource = ArrayLV.getAlignmentSource(); + BaseInfo = ArrayLV.getBaseInfo(); } else { // The base must be a pointer; emit it with an estimate of its alignment. - Addr = EmitPointerWithAlignment(E->getBase(), &AlignSource); + Addr = EmitPointerWithAlignment(E->getBase(), &BaseInfo); auto *Idx = EmitIdxAfterBase(/*Promote*/true); Addr = emitArraySubscriptGEP(*this, Addr, Idx, E->getType(), !getLangOpts().isSignedOverflowDefined()); } - LValue LV = MakeAddrLValue(Addr, E->getType(), AlignSource); + LValue LV = MakeAddrLValue(Addr, E->getType(), BaseInfo); // TODO: Preserve/extend path TBAA metadata? @@ -3193,7 +3210,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, } static Address emitOMPArraySectionBase(CodeGenFunction &CGF, const Expr *Base, - AlignmentSource &AlignSource, + LValueBaseInfo &BaseInfo, QualType BaseTy, QualType ElTy, bool IsLowerBound) { LValue BaseLVal; @@ -3201,7 +3218,7 @@ static Address emitOMPArraySectionBase(CodeGenFunction &CGF, const Expr *Base, BaseLVal = CGF.EmitOMPArraySectionExpr(ASE, IsLowerBound); if (BaseTy->isArrayType()) { Address Addr = BaseLVal.getAddress(); - AlignSource = BaseLVal.getAlignmentSource(); + BaseInfo = BaseLVal.getBaseInfo(); // If the array type was an incomplete type, we need to make sure // the decay ends up being the right type. @@ -3220,10 +3237,12 @@ static Address emitOMPArraySectionBase(CodeGenFunction &CGF, const Expr *Base, return CGF.Builder.CreateElementBitCast(Addr, CGF.ConvertTypeForMem(ElTy)); } - CharUnits Align = CGF.getNaturalTypeAlignment(ElTy, &AlignSource); + LValueBaseInfo TypeInfo; + CharUnits Align = CGF.getNaturalTypeAlignment(ElTy, &TypeInfo); + BaseInfo.mergeForCast(TypeInfo); return Address(CGF.Builder.CreateLoad(BaseLVal.getAddress()), Align); } - return CGF.EmitPointerWithAlignment(Base, &AlignSource); + return CGF.EmitPointerWithAlignment(Base, &BaseInfo); } LValue CodeGenFunction::EmitOMPArraySectionExpr(const OMPArraySectionExpr *E, @@ -3327,13 +3346,13 @@ LValue CodeGenFunction::EmitOMPArraySectionExpr(const OMPArraySectionExpr *E, assert(Idx); Address EltPtr = Address::invalid(); - AlignmentSource AlignSource; + LValueBaseInfo BaseInfo; if (auto *VLA = getContext().getAsVariableArrayType(ResultExprTy)) { // The base must be a pointer, which is not an aggregate. Emit // it. It needs to be emitted first in case it's what captures // the VLA bounds. Address Base = - emitOMPArraySectionBase(*this, E->getBase(), AlignSource, BaseTy, + emitOMPArraySectionBase(*this, E->getBase(), BaseInfo, BaseTy, VLA->getElementType(), IsLowerBound); // The element count here is the total number of non-VLA elements. llvm::Value *NumElements = getVLASize(VLA).first; @@ -3367,15 +3386,15 @@ LValue CodeGenFunction::EmitOMPArraySectionExpr(const OMPArraySectionExpr *E, EltPtr = emitArraySubscriptGEP( *this, ArrayLV.getAddress(), {CGM.getSize(CharUnits::Zero()), Idx}, ResultExprTy, !getLangOpts().isSignedOverflowDefined()); - AlignSource = ArrayLV.getAlignmentSource(); + BaseInfo = ArrayLV.getBaseInfo(); } else { - Address Base = emitOMPArraySectionBase(*this, E->getBase(), AlignSource, + Address Base = emitOMPArraySectionBase(*this, E->getBase(), BaseInfo, BaseTy, ResultExprTy, IsLowerBound); EltPtr = emitArraySubscriptGEP(*this, Base, Idx, ResultExprTy, !getLangOpts().isSignedOverflowDefined()); } - return MakeAddrLValue(EltPtr, ResultExprTy, AlignSource); + return MakeAddrLValue(EltPtr, ResultExprTy, BaseInfo); } LValue CodeGenFunction:: @@ -3387,10 +3406,10 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) { if (E->isArrow()) { // If it is a pointer to a vector, emit the address and form an lvalue with // it. - AlignmentSource AlignSource; - Address Ptr = EmitPointerWithAlignment(E->getBase(), &AlignSource); + LValueBaseInfo BaseInfo; + Address Ptr = EmitPointerWithAlignment(E->getBase(), &BaseInfo); const PointerType *PT = E->getBase()->getType()->getAs(); - Base = MakeAddrLValue(Ptr, PT->getPointeeType(), AlignSource); + Base = MakeAddrLValue(Ptr, PT->getPointeeType(), BaseInfo); Base.getQuals().removeObjCGCAttr(); } else if (E->getBase()->isGLValue()) { // Otherwise, if the base is an lvalue ( as in the case of foo.x.x), @@ -3407,7 +3426,7 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) { Address VecMem = CreateMemTemp(E->getBase()->getType()); Builder.CreateStore(Vec, VecMem); Base = MakeAddrLValue(VecMem, E->getBase()->getType(), - AlignmentSource::Decl); + LValueBaseInfo(AlignmentSource::Decl, false)); } QualType type = @@ -3421,7 +3440,7 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) { llvm::Constant *CV = llvm::ConstantDataVector::get(getLLVMContext(), Indices); return LValue::MakeExtVectorElt(Base.getAddress(), CV, type, - Base.getAlignmentSource()); + Base.getBaseInfo()); } assert(Base.isExtVectorElt() && "Can only subscript lvalue vec elts here!"); @@ -3432,17 +3451,16 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) { CElts.push_back(BaseElts->getAggregateElement(Indices[i])); llvm::Constant *CV = llvm::ConstantVector::get(CElts); return LValue::MakeExtVectorElt(Base.getExtVectorAddress(), CV, type, - Base.getAlignmentSource()); + Base.getBaseInfo()); } LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) { Expr *BaseExpr = E->getBase(); - // If this is s.x, emit s as an lvalue. If it is s->x, emit s as a scalar. LValue BaseLV; if (E->isArrow()) { - AlignmentSource AlignSource; - Address Addr = EmitPointerWithAlignment(BaseExpr, &AlignSource); + LValueBaseInfo BaseInfo; + Address Addr = EmitPointerWithAlignment(BaseExpr, &BaseInfo); QualType PtrTy = BaseExpr->getType()->getPointeeType(); SanitizerSet SkippedChecks; bool IsBaseCXXThis = IsWrappedCXXThis(BaseExpr); @@ -3452,7 +3470,7 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) { SkippedChecks.set(SanitizerKind::Null, true); EmitTypeCheck(TCK_MemberAccess, E->getExprLoc(), Addr.getPointer(), PtrTy, /*Alignment=*/CharUnits::Zero(), SkippedChecks); - BaseLV = MakeAddrLValue(Addr, PtrTy, AlignSource); + BaseLV = MakeAddrLValue(Addr, PtrTy, BaseInfo); } else BaseLV = EmitCheckedLValue(BaseExpr, TCK_MemberAccess); @@ -3512,8 +3530,10 @@ static Address emitAddrOfFieldStorage(CodeGenFunction &CGF, Address base, LValue CodeGenFunction::EmitLValueForField(LValue base, const FieldDecl *field) { + LValueBaseInfo BaseInfo = base.getBaseInfo(); AlignmentSource fieldAlignSource = - getFieldAlignmentSource(base.getAlignmentSource()); + getFieldAlignmentSource(BaseInfo.getAlignmentSource()); + LValueBaseInfo FieldBaseInfo(fieldAlignSource, BaseInfo.getMayAlias()); if (field->isBitField()) { const CGRecordLayout &RL = @@ -3533,7 +3553,7 @@ LValue CodeGenFunction::EmitLValueForField(LValue base, QualType fieldType = field->getType().withCVRQualifiers(base.getVRQualifiers()); - return LValue::MakeBitfield(Addr, Info, fieldType, fieldAlignSource); + return LValue::MakeBitfield(Addr, Info, fieldType, FieldBaseInfo); } const RecordDecl *rec = field->getParent(); @@ -3574,7 +3594,8 @@ LValue CodeGenFunction::EmitLValueForField(LValue base, type = refType->getPointeeType(); CharUnits alignment = - getNaturalTypeAlignment(type, &fieldAlignSource, /*pointee*/ true); + getNaturalTypeAlignment(type, &FieldBaseInfo, /*pointee*/ true); + FieldBaseInfo.setMayAlias(false); addr = Address(load, alignment); // Qualifiers on the struct don't apply to the referencee, and @@ -3595,7 +3616,7 @@ LValue CodeGenFunction::EmitLValueForField(LValue base, if (field->hasAttr()) addr = EmitFieldAnnotations(field, addr); - LValue LV = MakeAddrLValue(addr, type, fieldAlignSource); + LValue LV = MakeAddrLValue(addr, type, FieldBaseInfo); LV.getQuals().addCVRQualifiers(cvr); if (TBAAPath) { const ASTRecordLayout &Layout = @@ -3636,14 +3657,18 @@ CodeGenFunction::EmitLValueForFieldInitialization(LValue Base, V = Builder.CreateElementBitCast(V, llvmType, Field->getName()); // TODO: access-path TBAA? - auto FieldAlignSource = getFieldAlignmentSource(Base.getAlignmentSource()); - return MakeAddrLValue(V, FieldType, FieldAlignSource); + LValueBaseInfo BaseInfo = Base.getBaseInfo(); + LValueBaseInfo FieldBaseInfo( + getFieldAlignmentSource(BaseInfo.getAlignmentSource()), + BaseInfo.getMayAlias()); + return MakeAddrLValue(V, FieldType, FieldBaseInfo); } LValue CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr *E){ + LValueBaseInfo BaseInfo(AlignmentSource::Decl, false); if (E->isFileScope()) { ConstantAddress GlobalPtr = CGM.GetAddrOfConstantCompoundLiteral(E); - return MakeAddrLValue(GlobalPtr, E->getType(), AlignmentSource::Decl); + return MakeAddrLValue(GlobalPtr, E->getType(), BaseInfo); } if (E->getType()->isVariablyModifiedType()) // make sure to emit the VLA size. @@ -3651,7 +3676,7 @@ LValue CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr *E){ Address DeclPtr = CreateMemTemp(E->getType(), ".compoundliteral"); const Expr *InitExpr = E->getInitializer(); - LValue Result = MakeAddrLValue(DeclPtr, E->getType(), AlignmentSource::Decl); + LValue Result = MakeAddrLValue(DeclPtr, E->getType(), BaseInfo); EmitAnyExprToMem(InitExpr, DeclPtr, E->getType().getQualifiers(), /*Init*/ true); @@ -3748,8 +3773,12 @@ EmitConditionalOperatorLValue(const AbstractConditionalOperator *expr) { phi->addIncoming(rhs->getPointer(), rhsBlock); Address result(phi, std::min(lhs->getAlignment(), rhs->getAlignment())); AlignmentSource alignSource = - std::max(lhs->getAlignmentSource(), rhs->getAlignmentSource()); - return MakeAddrLValue(result, expr->getType(), alignSource); + std::max(lhs->getBaseInfo().getAlignmentSource(), + rhs->getBaseInfo().getAlignmentSource()); + bool MayAlias = lhs->getBaseInfo().getMayAlias() || + rhs->getBaseInfo().getMayAlias(); + return MakeAddrLValue(result, expr->getType(), + LValueBaseInfo(alignSource, MayAlias)); } else { assert((lhs || rhs) && "both operands of glvalue conditional are throw-expressions?"); @@ -3847,7 +3876,7 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { This, DerivedClassDecl, E->path_begin(), E->path_end(), /*NullCheckValue=*/false, E->getExprLoc()); - return MakeAddrLValue(Base, E->getType(), LV.getAlignmentSource()); + return MakeAddrLValue(Base, E->getType(), LV.getBaseInfo()); } case CK_ToUnion: return EmitAggExprToLValue(E); @@ -3874,7 +3903,7 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { /*MayBeNull=*/false, CFITCK_DerivedCast, E->getLocStart()); - return MakeAddrLValue(Derived, E->getType(), LV.getAlignmentSource()); + return MakeAddrLValue(Derived, E->getType(), LV.getBaseInfo()); } case CK_LValueBitCast: { // This must be a reinterpret_cast (or c-style equivalent). @@ -3890,13 +3919,13 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { /*MayBeNull=*/false, CFITCK_UnrelatedCast, E->getLocStart()); - return MakeAddrLValue(V, E->getType(), LV.getAlignmentSource()); + return MakeAddrLValue(V, E->getType(), LV.getBaseInfo()); } case CK_ObjCObjectLValueCast: { LValue LV = EmitLValue(E->getSubExpr()); Address V = Builder.CreateElementBitCast(LV.getAddress(), ConvertType(E->getType())); - return MakeAddrLValue(V, E->getType(), LV.getAlignmentSource()); + return MakeAddrLValue(V, E->getType(), LV.getBaseInfo()); } case CK_ZeroToOCLQueue: llvm_unreachable("NULL to OpenCL queue lvalue cast is not valid"); @@ -4085,7 +4114,7 @@ LValue CodeGenFunction::EmitCallExprLValue(const CallExpr *E) { if (!RV.isScalar()) return MakeAddrLValue(RV.getAggregateAddress(), E->getType(), - AlignmentSource::Decl); + LValueBaseInfo(AlignmentSource::Decl, false)); assert(E->getCallReturnType(getContext())->isReferenceType() && "Can't have a scalar return unless the return type is a " @@ -4105,7 +4134,7 @@ LValue CodeGenFunction::EmitCXXConstructLValue(const CXXConstructExpr *E) { AggValueSlot Slot = CreateAggTemp(E->getType()); EmitCXXConstructExpr(E, Slot); return MakeAddrLValue(Slot.getAddress(), E->getType(), - AlignmentSource::Decl); + LValueBaseInfo(AlignmentSource::Decl, false)); } LValue @@ -4120,7 +4149,7 @@ Address CodeGenFunction::EmitCXXUuidofExpr(const CXXUuidofExpr *E) { LValue CodeGenFunction::EmitCXXUuidofLValue(const CXXUuidofExpr *E) { return MakeAddrLValue(EmitCXXUuidofExpr(E), E->getType(), - AlignmentSource::Decl); + LValueBaseInfo(AlignmentSource::Decl, false)); } LValue @@ -4130,7 +4159,7 @@ CodeGenFunction::EmitCXXBindTemporaryLValue(const CXXBindTemporaryExpr *E) { EmitAggExpr(E->getSubExpr(), Slot); EmitCXXTemporary(E->getTemporary(), E->getType(), Slot.getAddress()); return MakeAddrLValue(Slot.getAddress(), E->getType(), - AlignmentSource::Decl); + LValueBaseInfo(AlignmentSource::Decl, false)); } LValue @@ -4138,7 +4167,7 @@ CodeGenFunction::EmitLambdaLValue(const LambdaExpr *E) { AggValueSlot Slot = CreateAggTemp(E->getType(), "temp.lvalue"); EmitLambdaExpr(E, Slot); return MakeAddrLValue(Slot.getAddress(), E->getType(), - AlignmentSource::Decl); + LValueBaseInfo(AlignmentSource::Decl, false)); } LValue CodeGenFunction::EmitObjCMessageExprLValue(const ObjCMessageExpr *E) { @@ -4146,7 +4175,7 @@ LValue CodeGenFunction::EmitObjCMessageExprLValue(const ObjCMessageExpr *E) { if (!RV.isScalar()) return MakeAddrLValue(RV.getAggregateAddress(), E->getType(), - AlignmentSource::Decl); + LValueBaseInfo(AlignmentSource::Decl, false)); assert(E->getMethodDecl()->getReturnType()->isReferenceType() && "Can't have a scalar return unless the return type is a " @@ -4158,7 +4187,8 @@ LValue CodeGenFunction::EmitObjCMessageExprLValue(const ObjCMessageExpr *E) { LValue CodeGenFunction::EmitObjCSelectorLValue(const ObjCSelectorExpr *E) { Address V = CGM.getObjCRuntime().GetAddrOfSelector(*this, E->getSelector()); - return MakeAddrLValue(V, E->getType(), AlignmentSource::Decl); + return MakeAddrLValue(V, E->getType(), + LValueBaseInfo(AlignmentSource::Decl, false)); } llvm::Value *CodeGenFunction::EmitIvarOffset(const ObjCInterfaceDecl *Interface, @@ -4202,7 +4232,7 @@ LValue CodeGenFunction::EmitStmtExprLValue(const StmtExpr *E) { // Can only get l-value for message expression returning aggregate type RValue RV = EmitAnyExprToTemp(E); return MakeAddrLValue(RV.getAggregateAddress(), E->getType(), - AlignmentSource::Decl); + LValueBaseInfo(AlignmentSource::Decl, false)); } RValue CodeGenFunction::EmitCall(QualType CalleeType, const CGCallee &OrigCallee, @@ -4394,12 +4424,11 @@ EmitPointerToDataMemberBinaryExpr(const BinaryOperator *E) { const MemberPointerType *MPT = E->getRHS()->getType()->getAs(); - AlignmentSource AlignSource; + LValueBaseInfo BaseInfo; Address MemberAddr = - EmitCXXMemberDataPointerAddress(E, BaseAddr, OffsetV, MPT, - &AlignSource); + EmitCXXMemberDataPointerAddress(E, BaseAddr, OffsetV, MPT, &BaseInfo); - return MakeAddrLValue(MemberAddr, MPT->getPointeeType(), AlignSource); + return MakeAddrLValue(MemberAddr, MPT->getPointeeType(), BaseInfo); } /// Given the address of a temporary variable, produce an r-value of @@ -4407,7 +4436,8 @@ EmitPointerToDataMemberBinaryExpr(const BinaryOperator *E) { RValue CodeGenFunction::convertTempToRValue(Address addr, QualType type, SourceLocation loc) { - LValue lvalue = MakeAddrLValue(addr, type, AlignmentSource::Decl); + LValue lvalue = MakeAddrLValue(addr, type, + LValueBaseInfo(AlignmentSource::Decl, false)); switch (getEvaluationKind(type)) { case TEK_Complex: return RValue::getComplex(EmitLoadOfComplex(lvalue, loc)); @@ -4462,9 +4492,9 @@ static LValueOrRValue emitPseudoObjectExpr(CodeGenFunction &CGF, if (ov == resultExpr && ov->isRValue() && !forLValue && CodeGenFunction::hasAggregateEvaluationKind(ov->getType())) { CGF.EmitAggExpr(ov->getSourceExpr(), slot); - + LValueBaseInfo BaseInfo(AlignmentSource::Decl, false); LValue LV = CGF.MakeAddrLValue(slot.getAddress(), ov->getType(), - AlignmentSource::Decl); + BaseInfo); opaqueData = OVMA::bind(CGF, ov, LV); result.RV = slot.asRValue(); diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp index d02f074dd605..a9865f3703d4 100644 --- a/lib/CodeGen/CGExprCXX.cpp +++ b/lib/CodeGen/CGExprCXX.cpp @@ -1531,13 +1531,13 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { assert(E->getNumPlacementArgs() == 1); const Expr *arg = *E->placement_arguments().begin(); - AlignmentSource alignSource; - allocation = EmitPointerWithAlignment(arg, &alignSource); + LValueBaseInfo BaseInfo; + allocation = EmitPointerWithAlignment(arg, &BaseInfo); // The pointer expression will, in many cases, be an opaque void*. // In these cases, discard the computed alignment and use the // formal alignment of the allocated type. - if (alignSource != AlignmentSource::Decl) + if (BaseInfo.getAlignmentSource() != AlignmentSource::Decl) allocation = Address(allocation.getPointer(), allocAlign); // Set up allocatorArgs for the call to operator delete if it's not @@ -1658,8 +1658,9 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { // Passing pointer through invariant.group.barrier to avoid propagation of // vptrs information which may be included in previous type. + // To not break LTO with different optimizations levels, we do it regardless + // of optimization level. if (CGM.getCodeGenOpts().StrictVTablePointers && - CGM.getCodeGenOpts().OptimizationLevel > 0 && allocator->isReservedGlobalPlacementOperator()) result = Address(Builder.CreateInvariantGroupBarrier(result.getPointer()), result.getAlignment()); diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index b8d830ee9f3f..048b50d8261d 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -1579,10 +1579,9 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { } // Since target may map different address spaces in AST to the same address // space, an address space conversion may end up as a bitcast. - auto *Src = Visit(E); - return CGF.CGM.getTargetCodeGenInfo().performAddrSpaceCast(CGF, Src, - E->getType(), - DestTy); + return CGF.CGM.getTargetCodeGenInfo().performAddrSpaceCast( + CGF, Visit(E), E->getType()->getPointeeType().getAddressSpace(), + DestTy->getPointeeType().getAddressSpace(), ConvertType(DestTy)); } case CK_AtomicToNonAtomic: case CK_NonAtomicToAtomic: diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp index f4fbab3c2b83..820520121763 100644 --- a/lib/CodeGen/CGObjC.cpp +++ b/lib/CodeGen/CGObjC.cpp @@ -162,7 +162,7 @@ llvm::Value *CodeGenFunction::EmitObjCCollectionLiteral(const Expr *E, const Expr *Rhs = ALE->getElement(i); LValue LV = MakeAddrLValue( Builder.CreateConstArrayGEP(Objects, i, getPointerSize()), - ElementType, AlignmentSource::Decl); + ElementType, LValueBaseInfo(AlignmentSource::Decl, false)); llvm::Value *value = EmitScalarExpr(Rhs); EmitStoreThroughLValue(RValue::get(value), LV, true); @@ -174,7 +174,7 @@ llvm::Value *CodeGenFunction::EmitObjCCollectionLiteral(const Expr *E, const Expr *Key = DLE->getKeyValueElement(i).Key; LValue KeyLV = MakeAddrLValue( Builder.CreateConstArrayGEP(Keys, i, getPointerSize()), - ElementType, AlignmentSource::Decl); + ElementType, LValueBaseInfo(AlignmentSource::Decl, false)); llvm::Value *keyValue = EmitScalarExpr(Key); EmitStoreThroughLValue(RValue::get(keyValue), KeyLV, /*isInit=*/true); @@ -182,7 +182,7 @@ llvm::Value *CodeGenFunction::EmitObjCCollectionLiteral(const Expr *E, const Expr *Value = DLE->getKeyValueElement(i).Value; LValue ValueLV = MakeAddrLValue( Builder.CreateConstArrayGEP(Objects, i, getPointerSize()), - ElementType, AlignmentSource::Decl); + ElementType, LValueBaseInfo(AlignmentSource::Decl, false)); llvm::Value *valueValue = EmitScalarExpr(Value); EmitStoreThroughLValue(RValue::get(valueValue), ValueLV, /*isInit=*/true); if (TrackNeededObjects) { diff --git a/lib/CodeGen/CGObjCRuntime.cpp b/lib/CodeGen/CGObjCRuntime.cpp index 3da7ed230edd..3e3d04672357 100644 --- a/lib/CodeGen/CGObjCRuntime.cpp +++ b/lib/CodeGen/CGObjCRuntime.cpp @@ -138,7 +138,8 @@ LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF, Addr = CGF.Builder.CreateElementBitCast(Addr, llvm::Type::getIntNTy(CGF.getLLVMContext(), Info->StorageSize)); - return LValue::MakeBitfield(Addr, *Info, IvarTy, AlignmentSource::Decl); + return LValue::MakeBitfield(Addr, *Info, IvarTy, + LValueBaseInfo(AlignmentSource::Decl, false)); } namespace { diff --git a/lib/CodeGen/CGOpenMPRuntime.cpp b/lib/CodeGen/CGOpenMPRuntime.cpp index b256a88c47ad..601d662e55e6 100644 --- a/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/lib/CodeGen/CGOpenMPRuntime.cpp @@ -720,7 +720,7 @@ LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue( CodeGenFunction &CGF) { return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()), getThreadIDVariable()->getType(), - AlignmentSource::Decl); + LValueBaseInfo(AlignmentSource::Decl, false)); } CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM) @@ -3565,7 +3565,9 @@ static void emitPrivatesInit(CodeGenFunction &CGF, auto SharedRefLValue = CGF.EmitLValueForField(SrcBase, SharedField); SharedRefLValue = CGF.MakeAddrLValue( Address(SharedRefLValue.getPointer(), C.getDeclAlign(OriginalVD)), - SharedRefLValue.getType(), AlignmentSource::Decl); + SharedRefLValue.getType(), + LValueBaseInfo(AlignmentSource::Decl, + SharedRefLValue.getBaseInfo().getMayAlias())); QualType Type = OriginalVD->getType(); if (Type->isArrayType()) { // Initialize firstprivate array. diff --git a/lib/CodeGen/CGStmtOpenMP.cpp b/lib/CodeGen/CGStmtOpenMP.cpp index 19b6cbab66c9..c8c71dd83e97 100644 --- a/lib/CodeGen/CGStmtOpenMP.cpp +++ b/lib/CodeGen/CGStmtOpenMP.cpp @@ -327,14 +327,15 @@ CodeGenFunction::GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S) { continue; } + LValueBaseInfo BaseInfo(AlignmentSource::Decl, false); LValue ArgLVal = MakeAddrLValue(GetAddrOfLocalVar(Args[Cnt]), Args[Cnt]->getType(), - AlignmentSource::Decl); + BaseInfo); if (FD->hasCapturedVLAType()) { LValue CastedArgLVal = MakeAddrLValue(castValueFromUintptr(*this, FD->getType(), Args[Cnt]->getName(), ArgLVal), - FD->getType(), AlignmentSource::Decl); + FD->getType(), BaseInfo); auto *ExprArg = EmitLoadOfLValue(CastedArgLVal, SourceLocation()).getScalarVal(); auto VAT = FD->getCapturedVLAType(); @@ -991,7 +992,7 @@ static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( BaseLV.getPointer(), CGF.ConvertTypeForMem(ElTy)->getPointerTo()), BaseLV.getAlignment()), - BaseLV.getType(), BaseLV.getAlignmentSource()); + BaseLV.getType(), BaseLV.getBaseInfo()); } void CodeGenFunction::EmitOMPReductionClauseInit( diff --git a/lib/CodeGen/CGValue.h b/lib/CodeGen/CGValue.h index 53a376df6457..b768eb86367b 100644 --- a/lib/CodeGen/CGValue.h +++ b/lib/CodeGen/CGValue.h @@ -146,6 +146,25 @@ static inline AlignmentSource getFieldAlignmentSource(AlignmentSource Source) { return AlignmentSource::Decl; } +class LValueBaseInfo { + AlignmentSource AlignSource; + bool MayAlias; + +public: + explicit LValueBaseInfo(AlignmentSource Source = AlignmentSource::Type, + bool Alias = false) + : AlignSource(Source), MayAlias(Alias) {} + AlignmentSource getAlignmentSource() const { return AlignSource; } + void setAlignmentSource(AlignmentSource Source) { AlignSource = Source; } + bool getMayAlias() const { return MayAlias; } + void setMayAlias(bool Alias) { MayAlias = Alias; } + + void mergeForCast(const LValueBaseInfo &Info) { + setAlignmentSource(Info.getAlignmentSource()); + setMayAlias(getMayAlias() || Info.getMayAlias()); + } +}; + /// LValue - This represents an lvalue references. Because C/C++ allow /// bitfields, this is not a simple LLVM pointer, it may be a pointer plus a /// bitrange. @@ -200,7 +219,7 @@ class LValue { // to make the default bitfield pattern all-zeroes. bool ImpreciseLifetime : 1; - unsigned AlignSource : 2; + LValueBaseInfo BaseInfo; // This flag shows if a nontemporal load/stores should be used when accessing // this lvalue. @@ -218,7 +237,7 @@ class LValue { private: void Initialize(QualType Type, Qualifiers Quals, - CharUnits Alignment, AlignmentSource AlignSource, + CharUnits Alignment, LValueBaseInfo BaseInfo, llvm::MDNode *TBAAInfo = nullptr) { assert((!Alignment.isZero() || Type->isIncompleteType()) && "initializing l-value with zero alignment!"); @@ -227,7 +246,7 @@ class LValue { this->Alignment = Alignment.getQuantity(); assert(this->Alignment == Alignment.getQuantity() && "Alignment exceeds allowed max!"); - this->AlignSource = unsigned(AlignSource); + this->BaseInfo = BaseInfo; // Initialize Objective-C flags. this->Ivar = this->ObjIsArray = this->NonGC = this->GlobalObjCRef = false; @@ -316,12 +335,8 @@ class LValue { CharUnits getAlignment() const { return CharUnits::fromQuantity(Alignment); } void setAlignment(CharUnits A) { Alignment = A.getQuantity(); } - AlignmentSource getAlignmentSource() const { - return AlignmentSource(AlignSource); - } - void setAlignmentSource(AlignmentSource Source) { - AlignSource = unsigned(Source); - } + LValueBaseInfo getBaseInfo() const { return BaseInfo; } + void setBaseInfo(LValueBaseInfo Info) { BaseInfo = Info; } // simple lvalue llvm::Value *getPointer() const { @@ -370,7 +385,7 @@ class LValue { static LValue MakeAddr(Address address, QualType type, ASTContext &Context, - AlignmentSource alignSource, + LValueBaseInfo BaseInfo, llvm::MDNode *TBAAInfo = nullptr) { Qualifiers qs = type.getQualifiers(); qs.setObjCGCAttr(Context.getObjCGCAttrKind(type)); @@ -379,29 +394,29 @@ class LValue { R.LVType = Simple; assert(address.getPointer()->getType()->isPointerTy()); R.V = address.getPointer(); - R.Initialize(type, qs, address.getAlignment(), alignSource, TBAAInfo); + R.Initialize(type, qs, address.getAlignment(), BaseInfo, TBAAInfo); return R; } static LValue MakeVectorElt(Address vecAddress, llvm::Value *Idx, - QualType type, AlignmentSource alignSource) { + QualType type, LValueBaseInfo BaseInfo) { LValue R; R.LVType = VectorElt; R.V = vecAddress.getPointer(); R.VectorIdx = Idx; R.Initialize(type, type.getQualifiers(), vecAddress.getAlignment(), - alignSource); + BaseInfo); return R; } static LValue MakeExtVectorElt(Address vecAddress, llvm::Constant *Elts, - QualType type, AlignmentSource alignSource) { + QualType type, LValueBaseInfo BaseInfo) { LValue R; R.LVType = ExtVectorElt; R.V = vecAddress.getPointer(); R.VectorElts = Elts; R.Initialize(type, type.getQualifiers(), vecAddress.getAlignment(), - alignSource); + BaseInfo); return R; } @@ -414,12 +429,12 @@ class LValue { static LValue MakeBitfield(Address Addr, const CGBitFieldInfo &Info, QualType type, - AlignmentSource alignSource) { + LValueBaseInfo BaseInfo) { LValue R; R.LVType = BitField; R.V = Addr.getPointer(); R.BitFieldInfo = &Info; - R.Initialize(type, type.getQualifiers(), Addr.getAlignment(), alignSource); + R.Initialize(type, type.getQualifiers(), Addr.getAlignment(), BaseInfo); return R; } @@ -428,7 +443,7 @@ class LValue { R.LVType = GlobalReg; R.V = Reg.getPointer(); R.Initialize(type, type.getQualifiers(), Reg.getAlignment(), - AlignmentSource::Decl); + LValueBaseInfo(AlignmentSource::Decl, false)); return R; } diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index 7b42850df968..85da3ae47db0 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -117,25 +117,27 @@ CodeGenFunction::~CodeGenFunction() { } CharUnits CodeGenFunction::getNaturalPointeeTypeAlignment(QualType T, - AlignmentSource *Source) { - return getNaturalTypeAlignment(T->getPointeeType(), Source, + LValueBaseInfo *BaseInfo) { + return getNaturalTypeAlignment(T->getPointeeType(), BaseInfo, /*forPointee*/ true); } CharUnits CodeGenFunction::getNaturalTypeAlignment(QualType T, - AlignmentSource *Source, + LValueBaseInfo *BaseInfo, bool forPointeeType) { // Honor alignment typedef attributes even on incomplete types. // We also honor them straight for C++ class types, even as pointees; // there's an expressivity gap here. if (auto TT = T->getAs()) { if (auto Align = TT->getDecl()->getMaxAlignment()) { - if (Source) *Source = AlignmentSource::AttributedType; + if (BaseInfo) + *BaseInfo = LValueBaseInfo(AlignmentSource::AttributedType, false); return getContext().toCharUnitsFromBits(Align); } } - if (Source) *Source = AlignmentSource::Type; + if (BaseInfo) + *BaseInfo = LValueBaseInfo(AlignmentSource::Type, false); CharUnits Alignment; if (T->isIncompleteType()) { @@ -165,9 +167,9 @@ CharUnits CodeGenFunction::getNaturalTypeAlignment(QualType T, } LValue CodeGenFunction::MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T) { - AlignmentSource AlignSource; - CharUnits Alignment = getNaturalTypeAlignment(T, &AlignSource); - return LValue::MakeAddr(Address(V, Alignment), T, getContext(), AlignSource, + LValueBaseInfo BaseInfo; + CharUnits Alignment = getNaturalTypeAlignment(T, &BaseInfo); + return LValue::MakeAddr(Address(V, Alignment), T, getContext(), BaseInfo, CGM.getTBAAInfo(T)); } @@ -175,9 +177,9 @@ LValue CodeGenFunction::MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T) { /// construct an l-value with the natural pointee alignment of T. LValue CodeGenFunction::MakeNaturalAlignPointeeAddrLValue(llvm::Value *V, QualType T) { - AlignmentSource AlignSource; - CharUnits Align = getNaturalTypeAlignment(T, &AlignSource, /*pointee*/ true); - return MakeAddrLValue(Address(V, Align), T, AlignSource); + LValueBaseInfo BaseInfo; + CharUnits Align = getNaturalTypeAlignment(T, &BaseInfo, /*pointee*/ true); + return MakeAddrLValue(Address(V, Align), T, BaseInfo); } diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 459841aee5a2..526ef9a1e579 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -1886,31 +1886,33 @@ class CodeGenFunction : public CodeGenTypeCache { //===--------------------------------------------------------------------===// LValue MakeAddrLValue(Address Addr, QualType T, - AlignmentSource AlignSource = AlignmentSource::Type) { - return LValue::MakeAddr(Addr, T, getContext(), AlignSource, + LValueBaseInfo BaseInfo = + LValueBaseInfo(AlignmentSource::Type)) { + return LValue::MakeAddr(Addr, T, getContext(), BaseInfo, CGM.getTBAAInfo(T)); } LValue MakeAddrLValue(llvm::Value *V, QualType T, CharUnits Alignment, - AlignmentSource AlignSource = AlignmentSource::Type) { + LValueBaseInfo BaseInfo = + LValueBaseInfo(AlignmentSource::Type)) { return LValue::MakeAddr(Address(V, Alignment), T, getContext(), - AlignSource, CGM.getTBAAInfo(T)); + BaseInfo, CGM.getTBAAInfo(T)); } LValue MakeNaturalAlignPointeeAddrLValue(llvm::Value *V, QualType T); LValue MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T); CharUnits getNaturalTypeAlignment(QualType T, - AlignmentSource *Source = nullptr, + LValueBaseInfo *BaseInfo = nullptr, bool forPointeeType = false); CharUnits getNaturalPointeeTypeAlignment(QualType T, - AlignmentSource *Source = nullptr); + LValueBaseInfo *BaseInfo = nullptr); Address EmitLoadOfReference(Address Ref, const ReferenceType *RefTy, - AlignmentSource *Source = nullptr); + LValueBaseInfo *BaseInfo = nullptr); LValue EmitLoadOfReferenceLValue(Address Ref, const ReferenceType *RefTy); Address EmitLoadOfPointer(Address Ptr, const PointerType *PtrTy, - AlignmentSource *Source = nullptr); + LValueBaseInfo *BaseInfo = nullptr); LValue EmitLoadOfPointerLValue(Address Ptr, const PointerType *PtrTy); /// CreateTempAlloca - This creates a alloca and inserts it into the entry @@ -2992,8 +2994,8 @@ class CodeGenFunction : public CodeGenTypeCache { /// the LLVM value representation. llvm::Value *EmitLoadOfScalar(Address Addr, bool Volatile, QualType Ty, SourceLocation Loc, - AlignmentSource AlignSource = - AlignmentSource::Type, + LValueBaseInfo BaseInfo = + LValueBaseInfo(AlignmentSource::Type), llvm::MDNode *TBAAInfo = nullptr, QualType TBAABaseTy = QualType(), uint64_t TBAAOffset = 0, @@ -3010,7 +3012,8 @@ class CodeGenFunction : public CodeGenTypeCache { /// the LLVM value representation. void EmitStoreOfScalar(llvm::Value *Value, Address Addr, bool Volatile, QualType Ty, - AlignmentSource AlignSource = AlignmentSource::Type, + LValueBaseInfo BaseInfo = + LValueBaseInfo(AlignmentSource::Type), llvm::MDNode *TBAAInfo = nullptr, bool isInit = false, QualType TBAABaseTy = QualType(), uint64_t TBAAOffset = 0, bool isNontemporal = false); @@ -3083,7 +3086,7 @@ class CodeGenFunction : public CodeGenTypeCache { RValue EmitRValueForField(LValue LV, const FieldDecl *FD, SourceLocation Loc); Address EmitArrayToPointerDecay(const Expr *Array, - AlignmentSource *AlignSource = nullptr); + LValueBaseInfo *BaseInfo = nullptr); class ConstantEmission { llvm::PointerIntPair ValueAndIsReference; @@ -3224,7 +3227,7 @@ class CodeGenFunction : public CodeGenTypeCache { Address EmitCXXMemberDataPointerAddress(const Expr *E, Address base, llvm::Value *memberPtr, const MemberPointerType *memberPtrType, - AlignmentSource *AlignSource = nullptr); + LValueBaseInfo *BaseInfo = nullptr); RValue EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E, ReturnValueSlot ReturnValue); @@ -3743,29 +3746,25 @@ class CodeGenFunction : public CodeGenTypeCache { unsigned ParamsToSkip = 0, EvaluationOrder Order = EvaluationOrder::Default); - /// EmitPointerWithAlignment - Given an expression with a pointer - /// type, emit the value and compute our best estimate of the - /// alignment of the pointee. + /// EmitPointerWithAlignment - Given an expression with a pointer type, + /// emit the value and compute our best estimate of the alignment of the + /// pointee. /// - /// Note that this function will conservatively fall back on the type - /// when it doesn't + /// \param BaseInfo - If non-null, this will be initialized with + /// information about the source of the alignment and the may-alias + /// attribute. Note that this function will conservatively fall back on + /// the type when it doesn't recognize the expression and may-alias will + /// be set to false. /// - /// \param Source - If non-null, this will be initialized with - /// information about the source of the alignment. Note that this - /// function will conservatively fall back on the type when it - /// doesn't recognize the expression, which means that sometimes - /// - /// a worst-case One - /// reasonable way to use this information is when there's a - /// language guarantee that the pointer must be aligned to some - /// stricter value, and we're simply trying to ensure that - /// sufficiently obvious uses of under-aligned objects don't get - /// miscompiled; for example, a placement new into the address of - /// a local variable. In such a case, it's quite reasonable to - /// just ignore the returned alignment when it isn't from an - /// explicit source. + /// One reasonable way to use this information is when there's a language + /// guarantee that the pointer must be aligned to some stricter value, and + /// we're simply trying to ensure that sufficiently obvious uses of under- + /// aligned objects don't get miscompiled; for example, a placement new + /// into the address of a local variable. In such a case, it's quite + /// reasonable to just ignore the returned alignment when it isn't from an + /// explicit source. Address EmitPointerWithAlignment(const Expr *Addr, - AlignmentSource *Source = nullptr); + LValueBaseInfo *BaseInfo = nullptr); void EmitSanitizerStatReport(llvm::SanitizerStatKind SSK); diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index a0254797ea43..9d0f802ece07 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -45,6 +45,7 @@ #include "clang/Frontend/CodeGenOptions.h" #include "clang/Sema/SemaDiagnostic.h" #include "llvm/ADT/Triple.h" +#include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/IR/CallSite.h" #include "llvm/IR/CallingConv.h" #include "llvm/IR/DataLayout.h" @@ -113,6 +114,7 @@ CodeGenModule::CodeGenModule(ASTContext &C, const HeaderSearchOptions &HSO, Int8PtrPtrTy = Int8PtrTy->getPointerTo(0); AllocaInt8PtrTy = Int8Ty->getPointerTo( M.getDataLayout().getAllocaAddrSpace()); + ASTAllocaAddressSpace = getTargetCodeGenInfo().getASTAllocaAddressSpace(); RuntimeCC = getTargetCodeGenInfo().getABIInfo().getRuntimeCC(); BuiltinCC = getTargetCodeGenInfo().getABIInfo().getBuiltinCC(); @@ -464,18 +466,24 @@ void CodeGenModule::Release() { getModule().addModuleFlag(llvm::Module::Warning, "Debug Info Version", llvm::DEBUG_METADATA_VERSION); + // Width of wchar_t in bytes + uint64_t WCharWidth = + Context.getTypeSizeInChars(Context.getWideCharType()).getQuantity(); + assert(LangOpts.ShortWChar || + llvm::TargetLibraryInfoImpl::getTargetWCharSize(Target.getTriple()) == + Target.getWCharWidth() / 8 && + "LLVM wchar_t size out of sync"); + // We need to record the widths of enums and wchar_t, so that we can generate - // the correct build attributes in the ARM backend. + // the correct build attributes in the ARM backend. wchar_size is also used by + // TargetLibraryInfo. + getModule().addModuleFlag(llvm::Module::Error, "wchar_size", WCharWidth); + llvm::Triple::ArchType Arch = Context.getTargetInfo().getTriple().getArch(); if ( Arch == llvm::Triple::arm || Arch == llvm::Triple::armeb || Arch == llvm::Triple::thumb || Arch == llvm::Triple::thumbeb) { - // Width of wchar_t in bytes - uint64_t WCharWidth = - Context.getTypeSizeInChars(Context.getWideCharType()).getQuantity(); - getModule().addModuleFlag(llvm::Module::Error, "wchar_size", WCharWidth); - // The minimum width of an enum in bytes uint64_t EnumWidth = Context.getLangOpts().ShortEnums ? 1 : 4; getModule().addModuleFlag(llvm::Module::Error, "min_enum_size", EnumWidth); diff --git a/lib/CodeGen/CodeGenTypeCache.h b/lib/CodeGen/CodeGenTypeCache.h index 8ce9860cc638..450eab48a3b4 100644 --- a/lib/CodeGen/CodeGenTypeCache.h +++ b/lib/CodeGen/CodeGenTypeCache.h @@ -94,6 +94,8 @@ struct CodeGenTypeCache { unsigned char SizeAlignInBytes; }; + unsigned ASTAllocaAddressSpace; + CharUnits getSizeSize() const { return CharUnits::fromQuantity(SizeSizeInBytes); } @@ -111,6 +113,8 @@ struct CodeGenTypeCache { llvm::CallingConv::ID getRuntimeCC() const { return RuntimeCC; } llvm::CallingConv::ID BuiltinCC; llvm::CallingConv::ID getBuiltinCC() const { return BuiltinCC; } + + unsigned getASTAllocaAddressSpace() const { return ASTAllocaAddressSpace; } }; } // end namespace CodeGen diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp index 18367d1602ba..83aa1fdf5722 100644 --- a/lib/CodeGen/TargetInfo.cpp +++ b/lib/CodeGen/TargetInfo.cpp @@ -407,12 +407,11 @@ llvm::Constant *TargetCodeGenInfo::getNullPointer(const CodeGen::CodeGenModule & } llvm::Value *TargetCodeGenInfo::performAddrSpaceCast( - CodeGen::CodeGenFunction &CGF, llvm::Value *Src, QualType SrcTy, - QualType DestTy) const { + CodeGen::CodeGenFunction &CGF, llvm::Value *Src, unsigned SrcAddr, + unsigned DestAddr, llvm::Type *DestTy, bool isNonNull) const { // Since target may map different address spaces in AST to the same address // space, an address space conversion may end up as a bitcast. - return CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Src, - CGF.ConvertType(DestTy)); + return CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Src, DestTy); } static bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays); @@ -6558,6 +6557,11 @@ class MIPSTargetCodeGenInfo : public TargetCodeGenInfo { Fn->addFnAttr("nomips16"); } + if (FD->hasAttr()) + Fn->addFnAttr("micromips"); + else if (FD->hasAttr()) + Fn->addFnAttr("nomicromips"); + const MipsInterruptAttr *Attr = FD->getAttr(); if (!Attr) return; @@ -7292,6 +7296,11 @@ class AMDGPUTargetCodeGenInfo : public TargetCodeGenInfo { llvm::Constant *getNullPointer(const CodeGen::CodeGenModule &CGM, llvm::PointerType *T, QualType QT) const override; + + unsigned getASTAllocaAddressSpace() const override { + return LangAS::FirstTargetAddressSpace + + getABIInfo().getDataLayout().getAllocaAddrSpace(); + } }; } diff --git a/lib/CodeGen/TargetInfo.h b/lib/CodeGen/TargetInfo.h index 223d6d047af7..247d01dcb086 100644 --- a/lib/CodeGen/TargetInfo.h +++ b/lib/CodeGen/TargetInfo.h @@ -229,13 +229,20 @@ class TargetCodeGenInfo { virtual llvm::Constant *getNullPointer(const CodeGen::CodeGenModule &CGM, llvm::PointerType *T, QualType QT) const; + /// Get the AST address space for alloca. + virtual unsigned getASTAllocaAddressSpace() const { return LangAS::Default; } + /// Perform address space cast of an expression of pointer type. /// \param V is the LLVM value to be casted to another address space. - /// \param SrcTy is the QualType of \p V. - /// \param DestTy is the destination QualType. + /// \param SrcAddr is the language address space of \p V. + /// \param DestAddr is the targeted language address space. + /// \param DestTy is the destination LLVM pointer type. + /// \param IsNonNull is the flag indicating \p V is known to be non null. virtual llvm::Value *performAddrSpaceCast(CodeGen::CodeGenFunction &CGF, - llvm::Value *V, QualType SrcTy, QualType DestTy) const; - + llvm::Value *V, unsigned SrcAddr, + unsigned DestAddr, + llvm::Type *DestTy, + bool IsNonNull = false) const; }; } // namespace CodeGen diff --git a/lib/Format/BreakableToken.cpp b/lib/Format/BreakableToken.cpp index c97486e4e4a7..3c9df62f80dc 100644 --- a/lib/Format/BreakableToken.cpp +++ b/lib/Format/BreakableToken.cpp @@ -41,7 +41,8 @@ static bool IsBlank(char C) { } static StringRef getLineCommentIndentPrefix(StringRef Comment) { - static const char *const KnownPrefixes[] = {"///", "//", "//!"}; + static const char *const KnownPrefixes[] = { + "///<", "//!<", "///", "//", "//!"}; StringRef LongestPrefix; for (StringRef KnownPrefix : KnownPrefixes) { if (Comment.startswith(KnownPrefix)) { @@ -77,6 +78,14 @@ static BreakableToken::Split getCommentSplit(StringRef Text, } StringRef::size_type SpaceOffset = Text.find_last_of(Blanks, MaxSplitBytes); + + // Do not split before a number followed by a dot: this would be interpreted + // as a numbered list, which would prevent re-flowing in subsequent passes. + static llvm::Regex kNumberedListRegexp = llvm::Regex("^[1-9][0-9]?\\."); + if (SpaceOffset != StringRef::npos && + kNumberedListRegexp.match(Text.substr(SpaceOffset).ltrim(Blanks))) + SpaceOffset = Text.find_last_of(Blanks, SpaceOffset); + if (SpaceOffset == StringRef::npos || // Don't break at leading whitespace. Text.find_last_not_of(Blanks, SpaceOffset) == StringRef::npos) { @@ -298,8 +307,9 @@ const FormatToken &BreakableComment::tokenAt(unsigned LineIndex) const { static bool mayReflowContent(StringRef Content) { Content = Content.trim(Blanks); // Lines starting with '@' commonly have special meaning. - static const SmallVector kSpecialMeaningPrefixes = { - "@", "TODO", "FIXME", "XXX"}; + // Lines starting with '-', '-#', '+' or '*' are bulleted/numbered lists. + static const SmallVector kSpecialMeaningPrefixes = { + "@", "TODO", "FIXME", "XXX", "-# ", "- ", "+ ", "* " }; bool hasSpecialMeaningPrefix = false; for (StringRef Prefix : kSpecialMeaningPrefixes) { if (Content.startswith(Prefix)) { @@ -307,6 +317,14 @@ static bool mayReflowContent(StringRef Content) { break; } } + + // Numbered lists may also start with a number followed by '.' + // To avoid issues if a line starts with a number which is actually the end + // of a previous line, we only consider numbers with up to 2 digits. + static llvm::Regex kNumberedListRegexp = llvm::Regex("^[1-9][0-9]?\\. "); + hasSpecialMeaningPrefix = hasSpecialMeaningPrefix || + kNumberedListRegexp.match(Content); + // Simple heuristic for what to reflow: content should contain at least two // characters and either the first or second character must be // non-punctuation. @@ -692,6 +710,10 @@ BreakableLineCommentSection::BreakableLineCommentSection( Prefix[i] = "/// "; else if (Prefix[i] == "//!") Prefix[i] = "//! "; + else if (Prefix[i] == "///<") + Prefix[i] = "///< "; + else if (Prefix[i] == "//!<") + Prefix[i] = "//!< "; } Tokens[i] = LineTok; diff --git a/lib/Format/ContinuationIndenter.cpp b/lib/Format/ContinuationIndenter.cpp index 488f9dd582f9..006a9710148f 100644 --- a/lib/Format/ContinuationIndenter.cpp +++ b/lib/Format/ContinuationIndenter.cpp @@ -207,7 +207,7 @@ bool ContinuationIndenter::mustBreak(const LineState &State) { // ... // }.bind(...)); // FIXME: We should find a more generic solution to this problem. - !(State.Column <= NewLineColumn && + !(State.Column <= NewLineColumn && Previous.isNot(tok::r_paren) && Style.Language == FormatStyle::LK_JavaScript)) return true; @@ -587,8 +587,10 @@ unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State, if (!DryRun) { unsigned Newlines = std::max( 1u, std::min(Current.NewlinesBefore, Style.MaxEmptyLinesToKeep + 1)); + bool ContinuePPDirective = + State.Line->InPPDirective && State.Line->Type != LT_ImportStatement; Whitespaces.replaceWhitespace(Current, Newlines, State.Column, State.Column, - State.Line->InPPDirective); + ContinuePPDirective); } if (!Current.isTrailingComment()) diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp index c8677e805179..ac83379e6b15 100644 --- a/lib/Format/Format.cpp +++ b/lib/Format/Format.cpp @@ -343,6 +343,8 @@ template <> struct MappingTraits { IO.mapOptional("ObjCSpaceAfterProperty", Style.ObjCSpaceAfterProperty); IO.mapOptional("ObjCSpaceBeforeProtocolList", Style.ObjCSpaceBeforeProtocolList); + IO.mapOptional("PenaltyBreakAssignment", + Style.PenaltyBreakAssignment); IO.mapOptional("PenaltyBreakBeforeFirstCallParameter", Style.PenaltyBreakBeforeFirstCallParameter); IO.mapOptional("PenaltyBreakComment", Style.PenaltyBreakComment); @@ -582,6 +584,7 @@ FormatStyle getLLVMStyle() { LLVMStyle.SpaceBeforeAssignmentOperators = true; LLVMStyle.SpacesInAngles = false; + LLVMStyle.PenaltyBreakAssignment = prec::Assignment; LLVMStyle.PenaltyBreakComment = 300; LLVMStyle.PenaltyBreakFirstLessLess = 120; LLVMStyle.PenaltyBreakString = 1000; diff --git a/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp index 387768a6ee56..79f438eb0f88 100644 --- a/lib/Format/TokenAnnotator.cpp +++ b/lib/Format/TokenAnnotator.cpp @@ -576,12 +576,13 @@ class AnnotatingParser { } break; case tok::kw_for: - if (Style.Language == FormatStyle::LK_JavaScript) + if (Style.Language == FormatStyle::LK_JavaScript) { if (Tok->Previous && Tok->Previous->is(tok::period)) break; - // JS' for async ( ... - if (CurrentToken->is(Keywords.kw_async)) + // JS' for await ( ... + if (CurrentToken && CurrentToken->is(Keywords.kw_await)) next(); + } Contexts.back().ColonIsForRangeExpr = true; next(); if (!parseParens()) @@ -703,9 +704,12 @@ class AnnotatingParser { void parseIncludeDirective() { if (CurrentToken && CurrentToken->is(tok::less)) { - next(); - while (CurrentToken) { - if (CurrentToken->isNot(tok::comment) || CurrentToken->Next) + next(); + while (CurrentToken) { + // Mark tokens up to the trailing line comments as implicit string + // literals. + if (CurrentToken->isNot(tok::comment) && + !CurrentToken->TokenText.startswith("//")) CurrentToken->Type = TT_ImplicitStringLiteral; next(); } @@ -2089,9 +2093,10 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line, if (Left.is(TT_ConditionalExpr)) return prec::Conditional; prec::Level Level = Left.getPrecedence(); - if (Level != prec::Unknown) - return Level; - Level = Right.getPrecedence(); + if (Level == prec::Unknown) + Level = Right.getPrecedence(); + if (Level == prec::Assignment) + return Style.PenaltyBreakAssignment; if (Level != prec::Unknown) return Level; @@ -2252,8 +2257,8 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line, } else if (Style.Language == FormatStyle::LK_JavaScript) { if (Left.is(TT_JsFatArrow)) return true; - // for async ( ... - if (Right.is(tok::l_paren) && Left.is(Keywords.kw_async) && + // for await ( ... + if (Right.is(tok::l_paren) && Left.is(Keywords.kw_await) && Left.Previous && Left.Previous->is(tok::kw_for)) return true; if (Left.is(Keywords.kw_async) && Right.is(tok::l_paren) && @@ -2472,22 +2477,25 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line, // If the last token before a '}', ']', or ')' is a comma or a trailing // comment, the intention is to insert a line break after it in order to make - // shuffling around entries easier. - const FormatToken *BeforeClosingBrace = nullptr; - if ((Left.isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) || - (Style.Language == FormatStyle::LK_JavaScript && - Left.is(tok::l_paren))) && - Left.BlockKind != BK_Block && Left.MatchingParen) - BeforeClosingBrace = Left.MatchingParen->Previous; - else if (Right.MatchingParen && - (Right.MatchingParen->isOneOf(tok::l_brace, - TT_ArrayInitializerLSquare) || - (Style.Language == FormatStyle::LK_JavaScript && - Right.MatchingParen->is(tok::l_paren)))) - BeforeClosingBrace = &Left; - if (BeforeClosingBrace && (BeforeClosingBrace->is(tok::comma) || - BeforeClosingBrace->isTrailingComment())) - return true; + // shuffling around entries easier. Import statements, especially in + // JavaScript, can be an exception to this rule. + if (Style.JavaScriptWrapImports || Line.Type != LT_ImportStatement) { + const FormatToken *BeforeClosingBrace = nullptr; + if ((Left.isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) || + (Style.Language == FormatStyle::LK_JavaScript && + Left.is(tok::l_paren))) && + Left.BlockKind != BK_Block && Left.MatchingParen) + BeforeClosingBrace = Left.MatchingParen->Previous; + else if (Right.MatchingParen && + (Right.MatchingParen->isOneOf(tok::l_brace, + TT_ArrayInitializerLSquare) || + (Style.Language == FormatStyle::LK_JavaScript && + Right.MatchingParen->is(tok::l_paren)))) + BeforeClosingBrace = &Left; + if (BeforeClosingBrace && (BeforeClosingBrace->is(tok::comma) || + BeforeClosingBrace->isTrailingComment())) + return true; + } if (Right.is(tok::comment)) return Left.BlockKind != BK_BracedInit && @@ -2562,7 +2570,7 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line, Keywords.kw_interface, Keywords.kw_type, tok::kw_static, tok::kw_public, tok::kw_private, tok::kw_protected, Keywords.kw_abstract, Keywords.kw_get, Keywords.kw_set)) - return false; // Otherwise a semicolon is inserted. + return false; // Otherwise automatic semicolon insertion would trigger. if (Left.is(TT_JsFatArrow) && Right.is(tok::l_brace)) return false; if (Left.is(TT_JsTypeColon)) diff --git a/lib/Format/UnwrappedLineFormatter.cpp b/lib/Format/UnwrappedLineFormatter.cpp index 8ff893426e25..01504da0a29b 100644 --- a/lib/Format/UnwrappedLineFormatter.cpp +++ b/lib/Format/UnwrappedLineFormatter.cpp @@ -611,7 +611,8 @@ class NoLineBreakFormatter : public LineFormatter { LineState State = Indenter->getInitialState(FirstIndent, &Line, DryRun); while (State.NextToken) { formatChildren(State, /*Newline=*/false, DryRun, Penalty); - Indenter->addTokenToState(State, /*Newline=*/false, DryRun); + Indenter->addTokenToState( + State, /*Newline=*/State.NextToken->MustBreakBefore, DryRun); } return Penalty; } diff --git a/lib/Format/UnwrappedLineParser.cpp b/lib/Format/UnwrappedLineParser.cpp index 31c66ffb00a1..ae79ea5d8a66 100644 --- a/lib/Format/UnwrappedLineParser.cpp +++ b/lib/Format/UnwrappedLineParser.cpp @@ -55,13 +55,33 @@ class ScopedDeclarationState { std::vector &Stack; }; +static bool isLineComment(const FormatToken &FormatTok) { + return FormatTok.is(tok::comment) && + FormatTok.TokenText.startswith("//"); +} + +// Checks if \p FormatTok is a line comment that continues the line comment +// \p Previous. The original column of \p MinColumnToken is used to determine +// whether \p FormatTok is indented enough to the right to continue \p Previous. +static bool continuesLineComment(const FormatToken &FormatTok, + const FormatToken *Previous, + const FormatToken *MinColumnToken) { + if (!Previous || !MinColumnToken) + return false; + unsigned MinContinueColumn = + MinColumnToken->OriginalColumn + (isLineComment(*MinColumnToken) ? 0 : 1); + return isLineComment(FormatTok) && FormatTok.NewlinesBefore == 1 && + isLineComment(*Previous) && + FormatTok.OriginalColumn >= MinContinueColumn; +} + class ScopedMacroState : public FormatTokenSource { public: ScopedMacroState(UnwrappedLine &Line, FormatTokenSource *&TokenSource, FormatToken *&ResetToken) : Line(Line), TokenSource(TokenSource), ResetToken(ResetToken), PreviousLineLevel(Line.Level), PreviousTokenSource(TokenSource), - Token(nullptr) { + Token(nullptr), PreviousToken(nullptr) { TokenSource = this; Line.Level = 0; Line.InPPDirective = true; @@ -78,6 +98,7 @@ class ScopedMacroState : public FormatTokenSource { // The \c UnwrappedLineParser guards against this by never calling // \c getNextToken() after it has encountered the first eof token. assert(!eof()); + PreviousToken = Token; Token = PreviousTokenSource->getNextToken(); if (eof()) return getFakeEOF(); @@ -87,12 +108,17 @@ class ScopedMacroState : public FormatTokenSource { unsigned getPosition() override { return PreviousTokenSource->getPosition(); } FormatToken *setPosition(unsigned Position) override { + PreviousToken = nullptr; Token = PreviousTokenSource->setPosition(Position); return Token; } private: - bool eof() { return Token && Token->HasUnescapedNewline; } + bool eof() { + return Token && Token->HasUnescapedNewline && + !continuesLineComment(*Token, PreviousToken, + /*MinColumnToken=*/PreviousToken); + } FormatToken *getFakeEOF() { static bool EOFInitialized = false; @@ -112,6 +138,7 @@ class ScopedMacroState : public FormatTokenSource { FormatTokenSource *PreviousTokenSource; FormatToken *Token; + FormatToken *PreviousToken; }; } // end anonymous namespace @@ -429,8 +456,9 @@ void UnwrappedLineParser::parseBlock(bool MustBeDeclaration, bool AddLevel, parseParens(); addUnwrappedLine(); - size_t OpeningLineIndex = - Lines.empty() ? (UnwrappedLine::kInvalidIndex) : (Lines.size() - 1); + size_t OpeningLineIndex = CurrentLines->empty() + ? (UnwrappedLine::kInvalidIndex) + : (CurrentLines->size() - 1); ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack, MustBeDeclaration); @@ -1635,9 +1663,9 @@ void UnwrappedLineParser::parseForOrWhileLoop() { assert(FormatTok->isOneOf(tok::kw_for, tok::kw_while, TT_ForEachMacro) && "'for', 'while' or foreach macro expected"); nextToken(); - // JS' for async ( ... + // JS' for await ( ... if (Style.Language == FormatStyle::LK_JavaScript && - FormatTok->is(Keywords.kw_async)) + FormatTok->is(Keywords.kw_await)) nextToken(); if (FormatTok->Tok.is(tok::l_paren)) parseParens(); @@ -2091,16 +2119,11 @@ bool UnwrappedLineParser::isOnNewLine(const FormatToken &FormatTok) { FormatTok.NewlinesBefore > 0; } -static bool isLineComment(const FormatToken &FormatTok) { - return FormatTok.is(tok::comment) && - FormatTok.TokenText.startswith("//"); -} - // Checks if \p FormatTok is a line comment that continues the line comment // section on \p Line. -static bool continuesLineComment(const FormatToken &FormatTok, - const UnwrappedLine &Line, - llvm::Regex &CommentPragmasRegex) { +static bool continuesLineCommentSection(const FormatToken &FormatTok, + const UnwrappedLine &Line, + llvm::Regex &CommentPragmasRegex) { if (Line.Tokens.empty()) return false; @@ -2199,12 +2222,8 @@ static bool continuesLineComment(const FormatToken &FormatTok, MinColumnToken = PreviousToken; } - unsigned MinContinueColumn = - MinColumnToken->OriginalColumn + - (isLineComment(*MinColumnToken) ? 0 : 1); - return isLineComment(FormatTok) && FormatTok.NewlinesBefore == 1 && - isLineComment(*(Line.Tokens.back().Tok)) && - FormatTok.OriginalColumn >= MinContinueColumn; + return continuesLineComment(FormatTok, /*Previous=*/Line.Tokens.back().Tok, + MinColumnToken); } void UnwrappedLineParser::flushComments(bool NewlineBeforeNext) { @@ -2222,7 +2241,7 @@ void UnwrappedLineParser::flushComments(bool NewlineBeforeNext) { // FIXME: Consider putting separate line comment sections as children to the // unwrapped line instead. (*I)->ContinuesLineCommentSection = - continuesLineComment(**I, *Line, CommentPragmasRegex); + continuesLineCommentSection(**I, *Line, CommentPragmasRegex); if (isOnNewLine(**I) && JustComments && !(*I)->ContinuesLineCommentSection) addUnwrappedLine(); pushToken(*I); @@ -2255,7 +2274,7 @@ void UnwrappedLineParser::distributeComments( const SmallVectorImpl &Comments, const FormatToken *NextTok) { // Whether or not a line comment token continues a line is controlled by - // the method continuesLineComment, with the following caveat: + // the method continuesLineCommentSection, with the following caveat: // // Define a trail of Comments to be a nonempty proper postfix of Comments such // that each comment line from the trail is aligned with the next token, if @@ -2293,7 +2312,7 @@ void UnwrappedLineParser::distributeComments( FormatTok->ContinuesLineCommentSection = false; } else { FormatTok->ContinuesLineCommentSection = - continuesLineComment(*FormatTok, *Line, CommentPragmasRegex); + continuesLineCommentSection(*FormatTok, *Line, CommentPragmasRegex); } if (!FormatTok->ContinuesLineCommentSection && (isOnNewLine(*FormatTok) || FormatTok->IsFirst)) { diff --git a/lib/Index/IndexBody.cpp b/lib/Index/IndexBody.cpp index 08d233fb83e0..efa5ed85d60b 100644 --- a/lib/Index/IndexBody.cpp +++ b/lib/Index/IndexBody.cpp @@ -246,6 +246,9 @@ class BodyIndexer : public RecursiveASTVisitor { } bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { + if (E->isClassReceiver()) + IndexCtx.handleReference(E->getClassReceiver(), E->getReceiverLocation(), + Parent, ParentDC); if (E->isExplicitProperty()) { SmallVector Relations; SymbolRoleSet Roles = getRolesForRef(E, Relations); diff --git a/lib/Index/IndexDecl.cpp b/lib/Index/IndexDecl.cpp index 203862c46e98..870b4e4fe825 100644 --- a/lib/Index/IndexDecl.cpp +++ b/lib/Index/IndexDecl.cpp @@ -63,6 +63,17 @@ class IndexingDeclVisitor : public ConstDeclVisitor { case TemplateArgument::Type: IndexCtx.indexTypeSourceInfo(LocInfo.getAsTypeSourceInfo(), Parent, DC); break; + case TemplateArgument::Template: + case TemplateArgument::TemplateExpansion: + IndexCtx.indexNestedNameSpecifierLoc(TALoc.getTemplateQualifierLoc(), + Parent, DC); + if (const TemplateDecl *TD = TALoc.getArgument() + .getAsTemplateOrTemplatePattern() + .getAsTemplateDecl()) { + if (const NamedDecl *TTD = TD->getTemplatedDecl()) + IndexCtx.handleReference(TTD, TALoc.getTemplateNameLoc(), Parent, DC); + } + break; default: break; } @@ -98,6 +109,17 @@ class IndexingDeclVisitor : public ConstDeclVisitor { } } } + } else { + // Index the default parameter value for function definitions. + if (const auto *FD = dyn_cast(D)) { + if (FD->isThisDeclarationADefinition()) { + for (const auto *PV : FD->parameters()) { + if (PV->hasDefaultArg() && !PV->hasUninstantiatedDefaultArg() && + !PV->hasUnparsedDefaultArg()) + IndexCtx.indexBody(PV->getDefaultArg(), D); + } + } + } } } @@ -206,9 +228,6 @@ class IndexingDeclVisitor : public ConstDeclVisitor { } bool VisitFunctionDecl(const FunctionDecl *D) { - if (D->isDeleted()) - return true; - SymbolRoleSet Roles{}; SmallVector Relations; if (auto *CXXMD = dyn_cast(D)) { @@ -568,8 +587,12 @@ class IndexingDeclVisitor : public ConstDeclVisitor { const DeclContext *DC = D->getDeclContext()->getRedeclContext(); const NamedDecl *Parent = dyn_cast(DC); - IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent, - D->getLexicalDeclContext()); + // NNS for the local 'using namespace' directives is visited by the body + // visitor. + if (!D->getParentFunctionOrMethod()) + IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent, + D->getLexicalDeclContext()); + return IndexCtx.handleReference(D->getNominatedNamespaceAsWritten(), D->getLocation(), Parent, D->getLexicalDeclContext(), @@ -598,8 +621,43 @@ class IndexingDeclVisitor : public ConstDeclVisitor { return true; } + static bool shouldIndexTemplateParameterDefaultValue(const NamedDecl *D) { + if (!D) + return false; + // We want to index the template parameters only once when indexing the + // canonical declaration. + if (const auto *FD = dyn_cast(D)) + return FD->getCanonicalDecl() == FD; + else if (const auto *TD = dyn_cast(D)) + return TD->getCanonicalDecl() == TD; + else if (const auto *VD = dyn_cast(D)) + return VD->getCanonicalDecl() == VD; + return true; + } + bool VisitTemplateDecl(const TemplateDecl *D) { // FIXME: Template parameters. + + // Index the default values for the template parameters. + const NamedDecl *Parent = D->getTemplatedDecl(); + if (D->getTemplateParameters() && + shouldIndexTemplateParameterDefaultValue(Parent)) { + const TemplateParameterList *Params = D->getTemplateParameters(); + for (const NamedDecl *TP : *Params) { + if (const auto *TTP = dyn_cast(TP)) { + if (TTP->hasDefaultArgument()) + IndexCtx.indexTypeSourceInfo(TTP->getDefaultArgumentInfo(), Parent); + } else if (const auto *NTTP = dyn_cast(TP)) { + if (NTTP->hasDefaultArgument()) + IndexCtx.indexBody(NTTP->getDefaultArgument(), Parent); + } else if (const auto *TTPD = dyn_cast(TP)) { + if (TTPD->hasDefaultArgument()) + handleTemplateArgumentLoc(TTPD->getDefaultArgument(), Parent, + /*DC=*/nullptr); + } + } + } + return Visit(D->getTemplatedDecl()); } diff --git a/lib/Index/IndexSymbol.cpp b/lib/Index/IndexSymbol.cpp index 0bfa19346b4e..0b20970acc3b 100644 --- a/lib/Index/IndexSymbol.cpp +++ b/lib/Index/IndexSymbol.cpp @@ -61,6 +61,8 @@ bool index::isFunctionLocalSymbol(const Decl *D) { if (isa(D)) return true; + if (isa(D)) + return false; if (!D->getParentFunctionOrMethod()) return false; @@ -318,16 +320,7 @@ SymbolInfo index::getSymbolInfo(const Decl *D) { if (Info.Properties & (unsigned)SymbolProperty::Generic) Info.Lang = SymbolLanguage::CXX; - auto getExternalSymAttr = [](const Decl *D) -> ExternalSourceSymbolAttr* { - if (auto *attr = D->getAttr()) - return attr; - if (auto *dcd = dyn_cast(D->getDeclContext())) { - if (auto *attr = dcd->getAttr()) - return attr; - } - return nullptr; - }; - if (auto *attr = getExternalSymAttr(D)) { + if (auto *attr = D->getExternalSourceSymbolAttr()) { if (attr->getLanguage() == "Swift") Info.Lang = SymbolLanguage::Swift; } diff --git a/lib/Index/USRGeneration.cpp b/lib/Index/USRGeneration.cpp index 044edf715fc2..21054b099a8e 100644 --- a/lib/Index/USRGeneration.cpp +++ b/lib/Index/USRGeneration.cpp @@ -49,7 +49,7 @@ static bool printLoc(llvm::raw_ostream &OS, SourceLocation Loc, static StringRef GetExternalSourceContainer(const NamedDecl *D) { if (!D) return StringRef(); - if (auto *attr = D->getAttr()) { + if (auto *attr = D->getExternalSourceSymbolAttr()) { return attr->getDefinedIn(); } return StringRef(); diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp index 6f44dc757e85..1f7003a2a4a7 100644 --- a/lib/Lex/ModuleMap.cpp +++ b/lib/Lex/ModuleMap.cpp @@ -950,39 +950,6 @@ bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) { return !Mod->UnresolvedConflicts.empty(); } -Module *ModuleMap::inferModuleFromLocation(FullSourceLoc Loc) { - if (Loc.isInvalid()) - return nullptr; - - if (UmbrellaDirs.empty() && Headers.empty()) - return nullptr; - - // Use the expansion location to determine which module we're in. - FullSourceLoc ExpansionLoc = Loc.getExpansionLoc(); - if (!ExpansionLoc.isFileID()) - return nullptr; - - const SourceManager &SrcMgr = Loc.getManager(); - FileID ExpansionFileID = ExpansionLoc.getFileID(); - - while (const FileEntry *ExpansionFile - = SrcMgr.getFileEntryForID(ExpansionFileID)) { - // Find the module that owns this header (if any). - if (Module *Mod = findModuleForHeader(ExpansionFile).getModule()) - return Mod; - - // No module owns this header, so look up the inclusion chain to see if - // any included header has an associated module. - SourceLocation IncludeLoc = SrcMgr.getIncludeLoc(ExpansionFileID); - if (IncludeLoc.isInvalid()) - return nullptr; - - ExpansionFileID = SrcMgr.getFileID(IncludeLoc); - } - - return nullptr; -} - //----------------------------------------------------------------------------// // Module map file parser //----------------------------------------------------------------------------// diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp index faf8809e4eb4..0534aeb10ccb 100644 --- a/lib/Lex/PPDirectives.cpp +++ b/lib/Lex/PPDirectives.cpp @@ -667,24 +667,17 @@ Module *Preprocessor::getModuleForLocation(SourceLocation Loc) { : HeaderInfo.lookupModule(getLangOpts().CurrentModule); } -Module *Preprocessor::getModuleContainingLocation(SourceLocation Loc) { - return HeaderInfo.getModuleMap().inferModuleFromLocation( - FullSourceLoc(Loc, SourceMgr)); -} - const FileEntry * Preprocessor::getModuleHeaderToIncludeForDiagnostics(SourceLocation IncLoc, + Module *M, SourceLocation Loc) { + assert(M && "no module to include"); + // If we have a module import syntax, we shouldn't include a header to // make a particular module visible. if (getLangOpts().ObjC2) return nullptr; - // Figure out which module we'd want to import. - Module *M = getModuleContainingLocation(Loc); - if (!M) - return nullptr; - Module *TopM = M->getTopLevelModule(); Module *IncM = getModuleForLocation(IncLoc); diff --git a/lib/Lex/PPLexerChange.cpp b/lib/Lex/PPLexerChange.cpp index 1938328c904d..5a589d6a17b3 100644 --- a/lib/Lex/PPLexerChange.cpp +++ b/lib/Lex/PPLexerChange.cpp @@ -731,7 +731,7 @@ Module *Preprocessor::LeaveSubmodule(bool ForPragma) { Module *LeavingMod = Info.M; SourceLocation ImportLoc = Info.ImportLoc; - if (!needModuleMacros() || + if (!needModuleMacros() || (!getLangOpts().ModulesLocalVisibility && LeavingMod->getTopLevelModuleName() != getLangOpts().CurrentModule)) { // If we don't need module macros, or this is not a module for which we @@ -777,17 +777,6 @@ Module *Preprocessor::LeaveSubmodule(bool ForPragma) { for (auto *MD = Macro.getLatest(); MD != OldMD; MD = MD->getPrevious()) { assert(MD && "broken macro directive chain"); - // Stop on macros defined in other submodules of this module that we - // #included along the way. There's no point doing this if we're - // tracking local submodule visibility, since there can be no such - // directives in our list. - if (!getLangOpts().ModulesLocalVisibility) { - Module *Mod = getModuleContainingLocation(MD->getLocation()); - if (Mod != LeavingMod && - Mod->getTopLevelModule() == LeavingMod->getTopLevelModule()) - break; - } - if (auto *VisMD = dyn_cast(MD)) { // The latest visibility directive for a name in a submodule affects // all the directives that come before it. @@ -809,6 +798,13 @@ Module *Preprocessor::LeaveSubmodule(bool ForPragma) { if (Def || !Macro.getOverriddenMacros().empty()) addModuleMacro(LeavingMod, II, Def, Macro.getOverriddenMacros(), IsNew); + + if (!getLangOpts().ModulesLocalVisibility) { + // This macro is exposed to the rest of this compilation as a + // ModuleMacro; we don't need to track its MacroDirective any more. + Macro.setLatest(nullptr); + Macro.setOverriddenMacros(*this, {}); + } break; } } diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp index 172b0edce5e4..cc1e8850a523 100644 --- a/lib/Parse/ParseCXXInlineMethods.cpp +++ b/lib/Parse/ParseCXXInlineMethods.cpp @@ -731,19 +731,6 @@ bool Parser::ConsumeAndStoreUntil(tok::TokenKind T1, tok::TokenKind T2, ConsumeBrace(); break; - case tok::code_completion: - Toks.push_back(Tok); - ConsumeCodeCompletionToken(); - break; - - case tok::string_literal: - case tok::wide_string_literal: - case tok::utf8_string_literal: - case tok::utf16_string_literal: - case tok::utf32_string_literal: - Toks.push_back(Tok); - ConsumeStringToken(); - break; case tok::semi: if (StopAtSemi) return false; @@ -751,7 +738,7 @@ bool Parser::ConsumeAndStoreUntil(tok::TokenKind T1, tok::TokenKind T2, default: // consume this token. Toks.push_back(Tok); - ConsumeToken(); + ConsumeAnyToken(/*ConsumeCodeCompletionTok*/true); break; } isFirstTokenConsumed = false; diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 4ccee74eaa90..b785f5f7d2e6 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -2989,7 +2989,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, } DS.getTypeSpecScope() = SS; - ConsumeToken(); // The C++ scope. + ConsumeAnnotationToken(); // The C++ scope. assert(Tok.is(tok::annot_template_id) && "ParseOptionalCXXScopeSpecifier not working"); AnnotateTemplateIdTokenAsType(); @@ -2998,7 +2998,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, if (Next.is(tok::annot_typename)) { DS.getTypeSpecScope() = SS; - ConsumeToken(); // The C++ scope. + ConsumeAnnotationToken(); // The C++ scope. if (Tok.getAnnotationValue()) { ParsedType T = getTypeAnnotation(Tok); isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, @@ -3010,7 +3010,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, else DS.SetTypeSpecError(); DS.SetRangeEnd(Tok.getAnnotationEndLoc()); - ConsumeToken(); // The typename + ConsumeAnnotationToken(); // The typename } if (Next.isNot(tok::identifier)) @@ -3037,7 +3037,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // C++ doesn't have implicit int. Diagnose it as a typo w.r.t. to the // typename. if (!TypeRep) { - ConsumeToken(); // Eat the scope spec so the identifier is current. + // Eat the scope spec so the identifier is current. + ConsumeAnnotationToken(); ParsedAttributesWithRange Attrs(AttrFactory); if (ParseImplicitInt(DS, &SS, TemplateInfo, AS, DSContext, Attrs)) { if (!Attrs.empty()) { @@ -3050,7 +3051,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, } DS.getTypeSpecScope() = SS; - ConsumeToken(); // The C++ scope. + ConsumeAnnotationToken(); // The C++ scope. isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID, TypeRep, Policy); @@ -3080,7 +3081,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, break; DS.SetRangeEnd(Tok.getAnnotationEndLoc()); - ConsumeToken(); // The typename + ConsumeAnnotationToken(); // The typename continue; } @@ -4836,10 +4837,12 @@ bool Parser::isConstructorDeclarator(bool IsUnqualified, bool DeductionGuide) { } // Parse the constructor name. - if (Tok.isOneOf(tok::identifier, tok::annot_template_id)) { + if (Tok.is(tok::identifier)) { // We already know that we have a constructor name; just consume // the token. ConsumeToken(); + } else if (Tok.is(tok::annot_template_id)) { + ConsumeAnnotationToken(); } else { TPA.Revert(); return false; @@ -4895,7 +4898,7 @@ bool Parser::isConstructorDeclarator(bool IsUnqualified, bool DeductionGuide) { // be a constructor declaration with an invalid argument type. Keep // looking. if (Tok.is(tok::annot_cxxscope)) - ConsumeToken(); + ConsumeAnnotationToken(); ConsumeToken(); // If this is not a constructor, we must be parsing a declarator, @@ -5539,11 +5542,28 @@ void Parser::ParseDirectDeclarator(Declarator &D) { D.SetRangeEnd(Tok.getLocation()); ConsumeToken(); goto PastIdentifier; - } else if (Tok.is(tok::identifier) && D.diagnoseIdentifier()) { - // A virt-specifier isn't treated as an identifier if it appears after a - // trailing-return-type. - if (D.getContext() != Declarator::TrailingReturnContext || - !isCXX11VirtSpecifier(Tok)) { + } else if (Tok.is(tok::identifier) && !D.mayHaveIdentifier()) { + // We're not allowed an identifier here, but we got one. Try to figure out + // if the user was trying to attach a name to the type, or whether the name + // is some unrelated trailing syntax. + bool DiagnoseIdentifier = false; + if (D.hasGroupingParens()) + // An identifier within parens is unlikely to be intended to be anything + // other than a name being "declared". + DiagnoseIdentifier = true; + else if (D.getContext() == Declarator::TemplateTypeArgContext) + // T is an accidental identifier; T'. + DiagnoseIdentifier = + NextToken().isOneOf(tok::comma, tok::greater, tok::greatergreater); + else if (D.getContext() == Declarator::AliasDeclContext || + D.getContext() == Declarator::AliasTemplateContext) + // The most likely error is that the ';' was forgotten. + DiagnoseIdentifier = NextToken().isOneOf(tok::comma, tok::semi); + else if (D.getContext() == Declarator::TrailingReturnContext && + !isCXX11VirtSpecifier(Tok)) + DiagnoseIdentifier = NextToken().isOneOf( + tok::comma, tok::semi, tok::equal, tok::l_brace, tok::kw_try); + if (DiagnoseIdentifier) { Diag(Tok.getLocation(), diag::err_unexpected_unqualified_id) << FixItHint::CreateRemoval(Tok.getLocation()); D.SetIdentifier(nullptr, Tok.getLocation()); diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index e6cf65e36cfa..527d45b1e203 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -901,7 +901,7 @@ SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) { if (Tok.is(tok::annot_decltype)) { Result = getExprAnnotation(Tok); EndLoc = Tok.getAnnotationEndLoc(); - ConsumeToken(); + ConsumeAnnotationToken(); if (Result.isInvalid()) { DS.SetTypeSpecError(); return EndLoc; @@ -1105,7 +1105,7 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc, assert(Tok.is(tok::annot_typename) && "template-id -> type failed"); ParsedType Type = getTypeAnnotation(Tok); EndLocation = Tok.getAnnotationEndLoc(); - ConsumeToken(); + ConsumeAnnotationToken(); if (Type) return Type; @@ -1162,7 +1162,7 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc, // return. EndLocation = Tok.getAnnotationEndLoc(); ParsedType Type = getTypeAnnotation(Tok); - ConsumeToken(); + ConsumeAnnotationToken(); return Type; } @@ -1565,7 +1565,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, } } else if (Tok.is(tok::annot_template_id)) { TemplateId = takeTemplateIdAnnotation(Tok); - NameLoc = ConsumeToken(); + NameLoc = ConsumeAnnotationToken(); if (TemplateId->Kind != TNK_Type_template && TemplateId->Kind != TNK_Dependent_template_name) { @@ -3405,38 +3405,41 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { // parse '::'[opt] nested-name-specifier[opt] CXXScopeSpec SS; ParseOptionalCXXScopeSpecifier(SS, nullptr, /*EnteringContext=*/false); + + // : identifier + IdentifierInfo *II = nullptr; + SourceLocation IdLoc = Tok.getLocation(); + // : declype(...) + DeclSpec DS(AttrFactory); + // : template_name<...> ParsedType TemplateTypeTy; - if (Tok.is(tok::annot_template_id)) { - TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok); - if (TemplateId->Kind == TNK_Type_template || - TemplateId->Kind == TNK_Dependent_template_name) { + + if (Tok.is(tok::identifier)) { + // Get the identifier. This may be a member name or a class name, + // but we'll let the semantic analysis determine which it is. + II = Tok.getIdentifierInfo(); + ConsumeToken(); + } else if (Tok.is(tok::annot_decltype)) { + // Get the decltype expression, if there is one. + // Uses of decltype will already have been converted to annot_decltype by + // ParseOptionalCXXScopeSpecifier at this point. + // FIXME: Can we get here with a scope specifier? + ParseDecltypeSpecifier(DS); + } else { + TemplateIdAnnotation *TemplateId = Tok.is(tok::annot_template_id) + ? takeTemplateIdAnnotation(Tok) + : nullptr; + if (TemplateId && (TemplateId->Kind == TNK_Type_template || + TemplateId->Kind == TNK_Dependent_template_name)) { AnnotateTemplateIdTokenAsType(/*IsClassName*/true); assert(Tok.is(tok::annot_typename) && "template-id -> type failed"); TemplateTypeTy = getTypeAnnotation(Tok); + ConsumeAnnotationToken(); + } else { + Diag(Tok, diag::err_expected_member_or_base_name); + return true; } } - // Uses of decltype will already have been converted to annot_decltype by - // ParseOptionalCXXScopeSpecifier at this point. - if (!TemplateTypeTy && Tok.isNot(tok::identifier) - && Tok.isNot(tok::annot_decltype)) { - Diag(Tok, diag::err_expected_member_or_base_name); - return true; - } - - IdentifierInfo *II = nullptr; - DeclSpec DS(AttrFactory); - SourceLocation IdLoc = Tok.getLocation(); - if (Tok.is(tok::annot_decltype)) { - // Get the decltype expression, if there is one. - ParseDecltypeSpecifier(DS); - } else { - if (Tok.is(tok::identifier)) - // Get the identifier. This may be a member name or a class name, - // but we'll let the semantic analysis determine which it is. - II = Tok.getIdentifierInfo(); - ConsumeToken(); - } - // Parse the '('. if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) { diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 727fd3500991..c739a50f0b38 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -192,6 +192,16 @@ Parser::ParseAssignmentExprWithObjCMessageExprStart(SourceLocation LBracLoc, return ParseRHSOfBinaryExpression(R, prec::Assignment); } +ExprResult +Parser::ParseConstantExpressionInExprEvalContext(TypeCastState isTypeCast) { + assert(Actions.ExprEvalContexts.back().Context == + Sema::ExpressionEvaluationContext::ConstantEvaluated && + "Call this function only if your ExpressionEvaluationContext is " + "already ConstantEvaluated"); + ExprResult LHS(ParseCastExpression(false, false, isTypeCast)); + ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::Conditional)); + return Actions.ActOnConstantExpression(Res); +} ExprResult Parser::ParseConstantExpression(TypeCastState isTypeCast) { // C++03 [basic.def.odr]p2: @@ -200,10 +210,7 @@ ExprResult Parser::ParseConstantExpression(TypeCastState isTypeCast) { // C++98 and C++11 have no such rule, but this is only a defect in C++98. EnterExpressionEvaluationContext ConstantEvaluated( Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated); - - ExprResult LHS(ParseCastExpression(false, false, isTypeCast)); - ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::Conditional)); - return Actions.ActOnConstantExpression(Res); + return ParseConstantExpressionInExprEvalContext(isTypeCast); } /// \brief Parse a constraint-expression. @@ -804,7 +811,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::annot_primary_expr: assert(Res.get() == nullptr && "Stray primary-expression annotation?"); Res = getExprAnnotation(Tok); - ConsumeToken(); + ConsumeAnnotationToken(); break; case tok::kw___super: @@ -1199,7 +1206,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, if (Ty.isInvalid()) break; - ConsumeToken(); + ConsumeAnnotationToken(); Res = ParseObjCMessageExpressionBody(SourceLocation(), SourceLocation(), Ty.get(), nullptr); break; diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index 56093f685617..0b210e0360a1 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -160,7 +160,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, Actions.RestoreNestedNameSpecifierAnnotation(Tok.getAnnotationValue(), Tok.getAnnotationRange(), SS); - ConsumeToken(); + ConsumeAnnotationToken(); return false; } @@ -346,7 +346,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, *LastII = TemplateId->Name; // Consume the template-id token. - ConsumeToken(); + ConsumeAnnotationToken(); assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!"); SourceLocation CCLoc = ConsumeToken(); @@ -920,7 +920,7 @@ Optional Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro, PP.AnnotateCachedTokens(Tok); // Consume the annotated initializer. - ConsumeToken(); + ConsumeAnnotationToken(); } } } else @@ -1528,7 +1528,7 @@ Parser::ParseCXXPseudoDestructor(Expr *Base, SourceLocation OpLoc, // store it in the pseudo-dtor node (to be used when instantiating it). FirstTypeName.setTemplateId( (TemplateIdAnnotation *)Tok.getAnnotationValue()); - ConsumeToken(); + ConsumeAnnotationToken(); assert(Tok.is(tok::coloncolon) &&"ParseOptionalCXXScopeSpecifier fail"); CCLoc = ConsumeToken(); } else { @@ -1882,7 +1882,7 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { DS.SetTypeSpecError(); DS.SetRangeEnd(Tok.getAnnotationEndLoc()); - ConsumeToken(); + ConsumeAnnotationToken(); DS.Finish(Actions, Policy); return; @@ -1951,11 +1951,8 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { DS.Finish(Actions, Policy); return; } - if (Tok.is(tok::annot_typename)) - DS.SetRangeEnd(Tok.getAnnotationEndLoc()); - else - DS.SetRangeEnd(Tok.getLocation()); - ConsumeToken(); + ConsumeAnyToken(); + DS.SetRangeEnd(PrevTokLocation); DS.Finish(Actions, Policy); } @@ -2529,12 +2526,12 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, /*NontrivialTypeSourceInfo=*/true); Result.setConstructorName(Ty, TemplateId->TemplateNameLoc, TemplateId->RAngleLoc); - ConsumeToken(); + ConsumeAnnotationToken(); return false; } Result.setConstructorTemplateId(TemplateId); - ConsumeToken(); + ConsumeAnnotationToken(); return false; } @@ -2542,7 +2539,7 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, // our unqualified-id. Result.setTemplateId(TemplateId); TemplateKWLoc = TemplateId->TemplateKWLoc; - ConsumeToken(); + ConsumeAnnotationToken(); return false; } diff --git a/lib/Parse/ParseOpenMP.cpp b/lib/Parse/ParseOpenMP.cpp index 86ac035f3c8c..b925dd7053dc 100644 --- a/lib/Parse/ParseOpenMP.cpp +++ b/lib/Parse/ParseOpenMP.cpp @@ -532,7 +532,7 @@ Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr, ConsumeAnyToken(); } // Skip the last annot_pragma_openmp_end. - SourceLocation EndLoc = ConsumeToken(); + SourceLocation EndLoc = ConsumeAnnotationToken(); if (!IsError) { return Actions.ActOnOpenMPDeclareSimdDirective( Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, Linears, @@ -562,7 +562,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!"); ParenBraceBracketBalancer BalancerRAIIObj(*this); - SourceLocation Loc = ConsumeToken(); + SourceLocation Loc = ConsumeAnnotationToken(); auto DKind = ParseOpenMPDirectiveKind(*this); switch (DKind) { @@ -578,7 +578,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); } // Skip the last annot_pragma_openmp_end. - ConsumeToken(); + ConsumeAnnotationToken(); return Actions.ActOnOpenMPThreadprivateDirective(Loc, Helper.getIdentifiers()); } @@ -596,7 +596,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( ConsumeAnyToken(); } // Skip the last annot_pragma_openmp_end. - ConsumeToken(); + ConsumeAnnotationToken(); return Res; } break; @@ -686,7 +686,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( ParseExternalDeclaration(attrs); if (Tok.isAnnotation() && Tok.is(tok::annot_pragma_openmp)) { TentativeParsingAction TPA(*this); - ConsumeToken(); + ConsumeAnnotationToken(); DKind = ParseOpenMPDirectiveKind(*this); if (DKind != OMPD_end_declare_target) TPA.Revert(); @@ -814,7 +814,7 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective( FirstClauses(OMPC_unknown + 1); unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope | Scope::OpenMPDirectiveScope; - SourceLocation Loc = ConsumeToken(), EndLoc; + SourceLocation Loc = ConsumeAnnotationToken(), EndLoc; auto DKind = ParseOpenMPDirectiveKind(*this); OpenMPDirectiveKind CancelRegion = OMPD_unknown; // Name of critical directive. @@ -973,7 +973,7 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective( // End location of the directive. EndLoc = Tok.getLocation(); // Consume final annot_pragma_openmp_end. - ConsumeToken(); + ConsumeAnnotationToken(); // OpenMP [2.13.8, ordered Construct, Syntax] // If the depend clause is specified, the ordered construct is a stand-alone diff --git a/lib/Parse/ParsePragma.cpp b/lib/Parse/ParsePragma.cpp index c34cd09a6238..18aebe658073 100644 --- a/lib/Parse/ParsePragma.cpp +++ b/lib/Parse/ParsePragma.cpp @@ -382,7 +382,7 @@ void Parser::resetPragmaHandlers() { /// annot_pragma_unused 'x' annot_pragma_unused 'y' void Parser::HandlePragmaUnused() { assert(Tok.is(tok::annot_pragma_unused)); - SourceLocation UnusedLoc = ConsumeToken(); + SourceLocation UnusedLoc = ConsumeAnnotationToken(); Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc); ConsumeToken(); // The argument token. } @@ -391,7 +391,7 @@ void Parser::HandlePragmaVisibility() { assert(Tok.is(tok::annot_pragma_vis)); const IdentifierInfo *VisType = static_cast(Tok.getAnnotationValue()); - SourceLocation VisLoc = ConsumeToken(); + SourceLocation VisLoc = ConsumeAnnotationToken(); Actions.ActOnPragmaVisibility(VisType, VisLoc); } @@ -407,7 +407,7 @@ void Parser::HandlePragmaPack() { assert(Tok.is(tok::annot_pragma_pack)); PragmaPackInfo *Info = static_cast(Tok.getAnnotationValue()); - SourceLocation PragmaLoc = ConsumeToken(); + SourceLocation PragmaLoc = ConsumeAnnotationToken(); ExprResult Alignment; if (Info->Alignment.is(tok::numeric_constant)) { Alignment = Actions.ActOnNumericConstant(Info->Alignment); @@ -423,7 +423,7 @@ void Parser::HandlePragmaMSStruct() { PragmaMSStructKind Kind = static_cast( reinterpret_cast(Tok.getAnnotationValue())); Actions.ActOnPragmaMSStruct(Kind); - ConsumeToken(); // The annotation token. + ConsumeAnnotationToken(); } void Parser::HandlePragmaAlign() { @@ -431,7 +431,7 @@ void Parser::HandlePragmaAlign() { Sema::PragmaOptionsAlignKind Kind = static_cast( reinterpret_cast(Tok.getAnnotationValue())); - SourceLocation PragmaLoc = ConsumeToken(); + SourceLocation PragmaLoc = ConsumeAnnotationToken(); Actions.ActOnPragmaOptionsAlign(Kind, PragmaLoc); } @@ -440,12 +440,12 @@ void Parser::HandlePragmaDump() { IdentifierInfo *II = reinterpret_cast(Tok.getAnnotationValue()); Actions.ActOnPragmaDump(getCurScope(), Tok.getLocation(), II); - ConsumeToken(); + ConsumeAnnotationToken(); } void Parser::HandlePragmaWeak() { assert(Tok.is(tok::annot_pragma_weak)); - SourceLocation PragmaLoc = ConsumeToken(); + SourceLocation PragmaLoc = ConsumeAnnotationToken(); Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc, Tok.getLocation()); ConsumeToken(); // The weak name. @@ -453,7 +453,7 @@ void Parser::HandlePragmaWeak() { void Parser::HandlePragmaWeakAlias() { assert(Tok.is(tok::annot_pragma_weakalias)); - SourceLocation PragmaLoc = ConsumeToken(); + SourceLocation PragmaLoc = ConsumeAnnotationToken(); IdentifierInfo *WeakName = Tok.getIdentifierInfo(); SourceLocation WeakNameLoc = Tok.getLocation(); ConsumeToken(); @@ -467,7 +467,7 @@ void Parser::HandlePragmaWeakAlias() { void Parser::HandlePragmaRedefineExtname() { assert(Tok.is(tok::annot_pragma_redefine_extname)); - SourceLocation RedefLoc = ConsumeToken(); + SourceLocation RedefLoc = ConsumeAnnotationToken(); IdentifierInfo *RedefName = Tok.getIdentifierInfo(); SourceLocation RedefNameLoc = Tok.getLocation(); ConsumeToken(); @@ -498,13 +498,13 @@ void Parser::HandlePragmaFPContract() { } Actions.ActOnPragmaFPContract(FPC); - ConsumeToken(); // The annotation token. + ConsumeAnnotationToken(); } StmtResult Parser::HandlePragmaCaptured() { assert(Tok.is(tok::annot_pragma_captured)); - ConsumeToken(); + ConsumeAnnotationToken(); if (Tok.isNot(tok::l_brace)) { PP.Diag(Tok, diag::err_expected) << tok::l_brace; @@ -541,7 +541,7 @@ void Parser::HandlePragmaOpenCLExtension() { auto State = Data->second; auto Ident = Data->first; SourceLocation NameLoc = Tok.getLocation(); - ConsumeToken(); // The annotation token. + ConsumeAnnotationToken(); auto &Opt = Actions.getOpenCLOptions(); auto Name = Ident->getName(); @@ -580,7 +580,7 @@ void Parser::HandlePragmaMSPointersToMembers() { LangOptions::PragmaMSPointersToMembersKind RepresentationMethod = static_cast( reinterpret_cast(Tok.getAnnotationValue())); - SourceLocation PragmaLoc = ConsumeToken(); // The annotation token. + SourceLocation PragmaLoc = ConsumeAnnotationToken(); Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc); } @@ -590,7 +590,7 @@ void Parser::HandlePragmaMSVtorDisp() { Sema::PragmaMsStackAction Action = static_cast((Value >> 16) & 0xFFFF); MSVtorDispAttr::Mode Mode = MSVtorDispAttr::Mode(Value & 0xFFFF); - SourceLocation PragmaLoc = ConsumeToken(); // The annotation token. + SourceLocation PragmaLoc = ConsumeAnnotationToken(); Actions.ActOnPragmaMSVtorDisp(Action, PragmaLoc, Mode); } @@ -600,7 +600,7 @@ void Parser::HandlePragmaMSPragma() { auto TheTokens = (std::pair, size_t> *)Tok.getAnnotationValue(); PP.EnterTokenStream(std::move(TheTokens->first), TheTokens->second, true); - SourceLocation PragmaLocation = ConsumeToken(); // The annotation token. + SourceLocation PragmaLocation = ConsumeAnnotationToken(); assert(Tok.isAnyIdentifier()); StringRef PragmaName = Tok.getIdentifierInfo()->getName(); PP.Lex(Tok); // pragma kind @@ -896,7 +896,7 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) { bool PragmaUnroll = PragmaNameInfo->getName() == "unroll"; bool PragmaNoUnroll = PragmaNameInfo->getName() == "nounroll"; if (Toks.empty() && (PragmaUnroll || PragmaNoUnroll)) { - ConsumeToken(); // The annotation token. + ConsumeAnnotationToken(); Hint.Range = Info->PragmaName.getLocation(); return true; } @@ -923,7 +923,7 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) { bool AssumeSafetyArg = !OptionUnroll && !OptionDistribute; // Verify loop hint has an argument. if (Toks[0].is(tok::eof)) { - ConsumeToken(); // The annotation token. + ConsumeAnnotationToken(); Diag(Toks[0].getLocation(), diag::err_pragma_loop_missing_argument) << /*StateArgument=*/StateOption << /*FullKeyword=*/OptionUnroll << /*AssumeSafetyKeyword=*/AssumeSafetyArg; @@ -932,7 +932,7 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) { // Validate the argument. if (StateOption) { - ConsumeToken(); // The annotation token. + ConsumeAnnotationToken(); SourceLocation StateLoc = Toks[0].getLocation(); IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo(); @@ -955,7 +955,7 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) { } else { // Enter constant expression including eof terminator into token stream. PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/false); - ConsumeToken(); // The annotation token. + ConsumeAnnotationToken(); ExprResult R = ParseConstantExpression(); @@ -1241,7 +1241,7 @@ void Parser::HandlePragmaAttribute() { SourceLocation PragmaLoc = Tok.getLocation(); auto *Info = static_cast(Tok.getAnnotationValue()); if (Info->Action == PragmaAttributeInfo::Pop) { - ConsumeToken(); + ConsumeAnnotationToken(); Actions.ActOnPragmaAttributePop(PragmaLoc); return; } @@ -1249,7 +1249,7 @@ void Parser::HandlePragmaAttribute() { assert(Info->Action == PragmaAttributeInfo::Push && "Unexpected #pragma attribute command"); PP.EnterTokenStream(Info->Tokens, /*DisableMacroExpansion=*/false); - ConsumeToken(); + ConsumeAnnotationToken(); ParsedAttributes &Attrs = Info->Attributes; Attrs.clearListOnly(); @@ -2526,7 +2526,7 @@ void Parser::HandlePragmaFP() { } Actions.ActOnPragmaFPContract(FPC); - ConsumeToken(); // The annotation token. + ConsumeAnnotationToken(); } /// \brief Parses loop or unroll pragma hint value and fills in Info. diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index 7d78046d0684..d147ab0a5674 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -338,13 +338,13 @@ Parser::ParseStatementOrDeclarationAfterAttributes(StmtVector &Stmts, case tok::annot_pragma_fp_contract: ProhibitAttributes(Attrs); Diag(Tok, diag::err_pragma_fp_contract_scope); - ConsumeToken(); + ConsumeAnnotationToken(); return StmtError(); case tok::annot_pragma_fp: ProhibitAttributes(Attrs); Diag(Tok, diag::err_pragma_fp_scope); - ConsumeToken(); + ConsumeAnnotationToken(); return StmtError(); case tok::annot_pragma_opencl_extension: diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp index 6a81e14ed496..a919d870810a 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -1186,7 +1186,13 @@ ParsedTemplateArgument Parser::ParseTemplateArgument() { // expression is resolved to a type-id, regardless of the form of // the corresponding template-parameter. // - // Therefore, we initially try to parse a type-id. + // Therefore, we initially try to parse a type-id - and isCXXTypeId might look + // up and annotate an identifier as an id-expression during disambiguation, + // so enter the appropriate context for a constant expression template + // argument before trying to disambiguate. + + EnterExpressionEvaluationContext EnterConstantEvaluated( + Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated); if (isCXXTypeId(TypeIdAsTemplateArgument)) { SourceLocation Loc = Tok.getLocation(); TypeResult TypeArg = ParseTypeName(/*Range=*/nullptr, @@ -1216,7 +1222,7 @@ ParsedTemplateArgument Parser::ParseTemplateArgument() { // Parse a non-type template argument. SourceLocation Loc = Tok.getLocation(); - ExprResult ExprArg = ParseConstantExpression(MaybeTypeCast); + ExprResult ExprArg = ParseConstantExpressionInExprEvalContext(MaybeTypeCast); if (ExprArg.isInvalid() || !ExprArg.get()) return ParsedTemplateArgument(); @@ -1234,7 +1240,7 @@ bool Parser::IsTemplateArgumentList(unsigned Skip) { } Tentative(*this); while (Skip) { - ConsumeToken(); + ConsumeAnyToken(); --Skip; } @@ -1248,7 +1254,7 @@ bool Parser::IsTemplateArgumentList(unsigned Skip) { // See whether we have declaration specifiers, which indicate a type. while (isCXXDeclarationSpecifier() == TPResult::True) - ConsumeToken(); + ConsumeAnyToken(); // If we have a '>' or a ',' then this is a template argument list. return Tok.isOneOf(tok::greater, tok::comma); @@ -1262,9 +1268,7 @@ bool Parser::IsTemplateArgumentList(unsigned Skip) { /// template-argument-list ',' template-argument bool Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) { - // Template argument lists are constant-evaluation contexts. - EnterExpressionEvaluationContext EvalContext( - Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated); + ColonProtectionRAIIObject ColonProtection(*this, false); do { diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp index 0ea3f8d95179..0d783131dd6e 100644 --- a/lib/Parse/ParseTentative.cpp +++ b/lib/Parse/ParseTentative.cpp @@ -208,17 +208,20 @@ Parser::TPResult Parser::TryConsumeDeclarationSpecifier() { TryAnnotateCXXScopeToken()) return TPResult::Error; if (Tok.is(tok::annot_cxxscope)) + ConsumeAnnotationToken(); + if (Tok.is(tok::identifier)) ConsumeToken(); - if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id)) + else if (Tok.is(tok::annot_template_id)) + ConsumeAnnotationToken(); + else return TPResult::Error; - ConsumeToken(); break; case tok::annot_cxxscope: - ConsumeToken(); + ConsumeAnnotationToken(); // Fall through. default: - ConsumeToken(); + ConsumeAnyToken(); if (getLangOpts().ObjC1 && Tok.is(tok::less)) return TryParseProtocolQualifiers(); @@ -478,10 +481,10 @@ Parser::isCXXConditionDeclarationOrInitStatement(bool CanBeInitStatement) { /// the corresponding ')'. If the context is /// TypeIdAsTemplateArgument, we've already parsed the '<' or ',' /// before this template argument, and will cease lookahead when we - /// hit a '>', '>>' (in C++0x), or ','. Returns true for a type-id - /// and false for an expression. If during the disambiguation - /// process a parsing error is encountered, the function returns - /// true to let the declaration parsing code handle it. + /// hit a '>', '>>' (in C++0x), or ','; or, in C++0x, an ellipsis immediately + /// preceding such. Returns true for a type-id and false for an expression. + /// If during the disambiguation process a parsing error is encountered, + /// the function returns true to let the declaration parsing code handle it. /// /// type-id: /// type-specifier-seq abstract-declarator[opt] @@ -530,10 +533,15 @@ bool Parser::isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous) { // We are supposed to be inside a template argument, so if after // the abstract declarator we encounter a '>', '>>' (in C++0x), or - // ',', this is a type-id. Otherwise, it's an expression. + // ','; or, in C++0x, an ellipsis immediately preceding such, this + // is a type-id. Otherwise, it's an expression. } else if (Context == TypeIdAsTemplateArgument && (Tok.isOneOf(tok::greater, tok::comma) || - (getLangOpts().CPlusPlus11 && Tok.is(tok::greatergreater)))) { + (getLangOpts().CPlusPlus11 && + (Tok.is(tok::greatergreater) || + (Tok.is(tok::ellipsis) && + NextToken().isOneOf(tok::greater, tok::greatergreater, + tok::comma)))))) { TPR = TPResult::True; isAmbiguous = true; @@ -706,7 +714,7 @@ Parser::TPResult Parser::TryParsePtrOperatorSeq() { if (Tok.isOneOf(tok::star, tok::amp, tok::caret, tok::ampamp) || (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::star))) { // ptr-operator - ConsumeToken(); + ConsumeAnyToken(); while (Tok.isOneOf(tok::kw_const, tok::kw_volatile, tok::kw_restrict, tok::kw__Nonnull, tok::kw__Nullable, tok::kw__Null_unspecified)) @@ -826,14 +834,14 @@ Parser::TPResult Parser::TryParseOperatorId() { /// abstract-declarator: /// ptr-operator abstract-declarator[opt] /// direct-abstract-declarator -/// ... /// /// direct-abstract-declarator: /// direct-abstract-declarator[opt] -/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt] +/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt] /// exception-specification[opt] /// direct-abstract-declarator[opt] '[' constant-expression[opt] ']' /// '(' abstract-declarator ')' +/// [C++0x] ... /// /// ptr-operator: /// '*' cv-qualifier-seq[opt] @@ -883,7 +891,7 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract, mayHaveIdentifier) { // declarator-id if (Tok.is(tok::annot_cxxscope)) - ConsumeToken(); + ConsumeAnnotationToken(); else if (Tok.is(tok::identifier)) TentativelyDeclaredIdentifiers.push_back(Tok.getIdentifierInfo()); if (Tok.is(tok::kw_operator)) { @@ -925,10 +933,6 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract, while (1) { TPResult TPR(TPResult::Ambiguous); - // abstract-declarator: ... - if (Tok.is(tok::ellipsis)) - ConsumeToken(); - if (Tok.is(tok::l_paren)) { // Check whether we have a function declarator or a possible ctor-style // initializer that follows the declarator. Note that ctor-style @@ -1399,7 +1403,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, SS); if (SS.getScopeRep() && SS.getScopeRep()->isDependent()) { RevertingTentativeParsingAction PA(*this); - ConsumeToken(); + ConsumeAnnotationToken(); ConsumeToken(); bool isIdentifier = Tok.is(tok::identifier); TPResult TPR = TPResult::False; @@ -1471,7 +1475,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, if (getLangOpts().ObjC1 && NextToken().is(tok::less)) { // Tentatively parse the protocol qualifiers. RevertingTentativeParsingAction PA(*this); - ConsumeToken(); // The type token + ConsumeAnyToken(); // The type token TPResult TPR = TryParseProtocolQualifiers(); bool isFollowedByParen = Tok.is(tok::l_paren); diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 38476ce7e15d..4fe038d271ad 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -337,21 +337,13 @@ bool Parser::SkipUntil(ArrayRef Toks, SkipUntilFlags Flags) { ConsumeBrace(); break; - case tok::string_literal: - case tok::wide_string_literal: - case tok::utf8_string_literal: - case tok::utf16_string_literal: - case tok::utf32_string_literal: - ConsumeStringToken(); - break; - case tok::semi: if (HasFlagsSet(Flags, StopAtSemi)) return false; // FALL THROUGH. default: // Skip this token. - ConsumeToken(); + ConsumeAnyToken(); break; } isFirstTokenSkipped = false; @@ -578,19 +570,19 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) { Actions.ActOnModuleInclude(Tok.getLocation(), reinterpret_cast( Tok.getAnnotationValue())); - ConsumeToken(); + ConsumeAnnotationToken(); return false; case tok::annot_module_begin: Actions.ActOnModuleBegin(Tok.getLocation(), reinterpret_cast( Tok.getAnnotationValue())); - ConsumeToken(); + ConsumeAnnotationToken(); return false; case tok::annot_module_end: Actions.ActOnModuleEnd(Tok.getLocation(), reinterpret_cast( Tok.getAnnotationValue())); - ConsumeToken(); + ConsumeAnnotationToken(); return false; case tok::annot_pragma_attribute: @@ -2169,7 +2161,7 @@ bool Parser::parseMisplacedModuleImport() { Actions.ActOnModuleEnd(Tok.getLocation(), reinterpret_cast( Tok.getAnnotationValue())); - ConsumeToken(); + ConsumeAnnotationToken(); continue; } // Inform caller that recovery failed, the error must be handled at upper @@ -2181,7 +2173,7 @@ bool Parser::parseMisplacedModuleImport() { Actions.ActOnModuleBegin(Tok.getLocation(), reinterpret_cast( Tok.getAnnotationValue())); - ConsumeToken(); + ConsumeAnnotationToken(); ++MisplacedModuleBeginCount; continue; case tok::annot_module_include: @@ -2190,7 +2182,7 @@ bool Parser::parseMisplacedModuleImport() { Actions.ActOnModuleInclude(Tok.getLocation(), reinterpret_cast( Tok.getAnnotationValue())); - ConsumeToken(); + ConsumeAnnotationToken(); // If there is another module import, process it. continue; default: diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index dca51b0e8c8e..5e937aa69963 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -2021,7 +2021,7 @@ bool Sema::isIncompatibleTypedef(TypeDecl *Old, TypedefNameDecl *New) { Diag(New->getLocation(), diag::err_redefinition_variably_modified_typedef) << Kind << NewType; if (Old->getLocation().isValid()) - notePreviousDefinition(Old->getLocation(), New->getLocation()); + notePreviousDefinition(Old, New->getLocation()); New->setInvalidDecl(); return true; } @@ -2034,7 +2034,7 @@ bool Sema::isIncompatibleTypedef(TypeDecl *Old, TypedefNameDecl *New) { Diag(New->getLocation(), diag::err_redefinition_different_typedef) << Kind << NewType << OldType; if (Old->getLocation().isValid()) - notePreviousDefinition(Old->getLocation(), New->getLocation()); + notePreviousDefinition(Old, New->getLocation()); New->setInvalidDecl(); return true; } @@ -2101,7 +2101,7 @@ void Sema::MergeTypedefNameDecl(Scope *S, TypedefNameDecl *New, NamedDecl *OldD = OldDecls.getRepresentativeDecl(); if (OldD->getLocation().isValid()) - notePreviousDefinition(OldD->getLocation(), New->getLocation()); + notePreviousDefinition(OldD, New->getLocation()); return New->setInvalidDecl(); } @@ -2193,7 +2193,7 @@ void Sema::MergeTypedefNameDecl(Scope *S, TypedefNameDecl *New, Diag(New->getLocation(), diag::err_redefinition) << New->getDeclName(); - notePreviousDefinition(Old->getLocation(), New->getLocation()); + notePreviousDefinition(Old, New->getLocation()); return New->setInvalidDecl(); } @@ -2214,7 +2214,7 @@ void Sema::MergeTypedefNameDecl(Scope *S, TypedefNameDecl *New, Diag(New->getLocation(), diag::ext_redefinition_of_typedef) << New->getDeclName(); - notePreviousDefinition(Old->getLocation(), New->getLocation()); + notePreviousDefinition(Old, New->getLocation()); } /// DeclhasAttr - returns true if decl Declaration already has the target @@ -2448,7 +2448,7 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D, return false; } -static const Decl *getDefinition(const Decl *D) { +static const NamedDecl *getDefinition(const Decl *D) { if (const TagDecl *TD = dyn_cast(D)) return TD->getDefinition(); if (const VarDecl *VD = dyn_cast(D)) { @@ -2475,7 +2475,7 @@ static void checkNewAttributesAfterDef(Sema &S, Decl *New, const Decl *Old) { if (!New->hasAttrs()) return; - const Decl *Def = getDefinition(Old); + const NamedDecl *Def = getDefinition(Old); if (!Def || Def == New) return; @@ -2502,7 +2502,7 @@ static void checkNewAttributesAfterDef(Sema &S, Decl *New, const Decl *Old) { : diag::err_redefinition; S.Diag(VD->getLocation(), Diag) << VD->getDeclName(); if (Diag == diag::err_redefinition) - S.notePreviousDefinition(Def->getLocation(), VD->getLocation()); + S.notePreviousDefinition(Def, VD->getLocation()); else S.Diag(Def->getLocation(), diag::note_previous_definition); VD->setInvalidDecl(); @@ -2891,7 +2891,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, } else { Diag(New->getLocation(), diag::err_redefinition_different_kind) << New->getDeclName(); - notePreviousDefinition(OldD->getLocation(), New->getLocation()); + notePreviousDefinition(OldD, New->getLocation()); return true; } } @@ -2928,7 +2928,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, !Old->hasAttr()) { Diag(New->getLocation(), diag::err_internal_linkage_redeclaration) << New->getDeclName(); - notePreviousDefinition(Old->getLocation(), New->getLocation()); + notePreviousDefinition(Old, New->getLocation()); New->dropAttr(); } @@ -3657,7 +3657,7 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { if (!Old) { Diag(New->getLocation(), diag::err_redefinition_different_kind) << New->getDeclName(); - notePreviousDefinition(Previous.getRepresentativeDecl()->getLocation(), + notePreviousDefinition(Previous.getRepresentativeDecl(), New->getLocation()); return New->setInvalidDecl(); } @@ -3687,7 +3687,7 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { Old->getStorageClass() == SC_None && !Old->hasAttr()) { Diag(New->getLocation(), diag::warn_weak_import) << New->getDeclName(); - notePreviousDefinition(Old->getLocation(), New->getLocation()); + notePreviousDefinition(Old, New->getLocation()); // Remove weak_import attribute on new declaration. New->dropAttr(); } @@ -3696,7 +3696,7 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { !Old->hasAttr()) { Diag(New->getLocation(), diag::err_internal_linkage_redeclaration) << New->getDeclName(); - notePreviousDefinition(Old->getLocation(), New->getLocation()); + notePreviousDefinition(Old, New->getLocation()); New->dropAttr(); } @@ -3853,29 +3853,22 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { New->setImplicitlyInline(); } -void Sema::notePreviousDefinition(SourceLocation Old, SourceLocation New) { +void Sema::notePreviousDefinition(const NamedDecl *Old, SourceLocation New) { SourceManager &SrcMgr = getSourceManager(); auto FNewDecLoc = SrcMgr.getDecomposedLoc(New); - auto FOldDecLoc = SrcMgr.getDecomposedLoc(Old); + auto FOldDecLoc = SrcMgr.getDecomposedLoc(Old->getLocation()); auto *FNew = SrcMgr.getFileEntryForID(FNewDecLoc.first); auto *FOld = SrcMgr.getFileEntryForID(FOldDecLoc.first); auto &HSI = PP.getHeaderSearchInfo(); - StringRef HdrFilename = SrcMgr.getFilename(SrcMgr.getSpellingLoc(Old)); + StringRef HdrFilename = + SrcMgr.getFilename(SrcMgr.getSpellingLoc(Old->getLocation())); - auto noteFromModuleOrInclude = [&](SourceLocation &Loc, - SourceLocation &IncLoc) -> bool { - Module *Mod = nullptr; + auto noteFromModuleOrInclude = [&](Module *Mod, + SourceLocation IncLoc) -> bool { // Redefinition errors with modules are common with non modular mapped // headers, example: a non-modular header H in module A that also gets // included directly in a TU. Pointing twice to the same header/definition // is confusing, try to get better diagnostics when modules is on. - if (getLangOpts().Modules) { - auto ModLoc = SrcMgr.getModuleImportLoc(Old); - if (!ModLoc.first.isInvalid()) - Mod = HSI.getModuleMap().inferModuleFromLocation( - FullSourceLoc(Loc, SrcMgr)); - } - if (IncLoc.isValid()) { if (Mod) { Diag(IncLoc, diag::note_redefinition_modules_same_file) @@ -3899,19 +3892,19 @@ void Sema::notePreviousDefinition(SourceLocation Old, SourceLocation New) { if (FNew == FOld && FNewDecLoc.second == FOldDecLoc.second) { SourceLocation OldIncLoc = SrcMgr.getIncludeLoc(FOldDecLoc.first); SourceLocation NewIncLoc = SrcMgr.getIncludeLoc(FNewDecLoc.first); - EmittedDiag = noteFromModuleOrInclude(Old, OldIncLoc); - EmittedDiag |= noteFromModuleOrInclude(New, NewIncLoc); + EmittedDiag = noteFromModuleOrInclude(Old->getOwningModule(), OldIncLoc); + EmittedDiag |= noteFromModuleOrInclude(getCurrentModule(), NewIncLoc); // If the header has no guards, emit a note suggesting one. if (FOld && !HSI.isFileMultipleIncludeGuarded(FOld)) - Diag(Old, diag::note_use_ifdef_guards); + Diag(Old->getLocation(), diag::note_use_ifdef_guards); if (EmittedDiag) return; } // Redefinition coming from different files or couldn't do better above. - Diag(Old, diag::note_previous_definition); + Diag(Old->getLocation(), diag::note_previous_definition); } /// We've just determined that \p Old and \p New both appear to be definitions @@ -3934,7 +3927,7 @@ bool Sema::checkVarDeclRedefinition(VarDecl *Old, VarDecl *New) { return false; } else { Diag(New->getLocation(), diag::err_redefinition) << New; - notePreviousDefinition(Old->getLocation(), New->getLocation()); + notePreviousDefinition(Old, New->getLocation()); New->setInvalidDecl(); return true; } @@ -6942,7 +6935,7 @@ void Sema::CheckShadow(NamedDecl *D, NamedDecl *ShadowedDecl, } } - DeclContext *OldDC = ShadowedDecl->getDeclContext(); + DeclContext *OldDC = ShadowedDecl->getDeclContext()->getRedeclContext(); unsigned WarningDiag = diag::warn_decl_shadow; SourceLocation CaptureLoc; @@ -7198,7 +7191,7 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) { // ISO/IEC TR 18037 S5.1.2 if (!getLangOpts().OpenCL && NewVD->hasLocalStorage() && T.getAddressSpace() != 0) { - Diag(NewVD->getLocation(), diag::err_as_qualified_auto_decl); + Diag(NewVD->getLocation(), diag::err_as_qualified_auto_decl) << 0; NewVD->setInvalidDecl(); return; } @@ -7278,6 +7271,11 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) { NewVD->setInvalidDecl(); return; } + } else if (T.getAddressSpace() != LangAS::Default) { + // Do not allow other address spaces on automatic variable. + Diag(NewVD->getLocation(), diag::err_as_qualified_auto_decl) << 1; + NewVD->setInvalidDecl(); + return; } } } @@ -13503,9 +13501,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, } else if (TUK == TUK_Reference && (PrevTagDecl->getFriendObjectKind() == Decl::FOK_Undeclared || - PP.getModuleContainingLocation( - PrevDecl->getLocation()) != - PP.getModuleContainingLocation(KWLoc)) && + PrevDecl->getOwningModule() != getCurrentModule()) && SS.isEmpty()) { // This declaration is a reference to an existing entity, but // has different visibility from that entity: it either makes @@ -13561,7 +13557,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, Diag(NameLoc, diag::warn_redefinition_in_param_list) << Name; else Diag(NameLoc, diag::err_redefinition) << Name; - notePreviousDefinition(Def->getLocation(), + notePreviousDefinition(Def, NameLoc.isValid() ? NameLoc : KWLoc); // If this is a redefinition, recover by making this // struct be anonymous, which will make any later @@ -13652,7 +13648,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // The tag name clashes with something else in the target scope, // issue an error and recover by making this tag be anonymous. Diag(NameLoc, diag::err_redefinition_different_kind) << Name; - notePreviousDefinition(PrevDecl->getLocation(), NameLoc); + notePreviousDefinition(PrevDecl, NameLoc); Name = nullptr; Invalid = true; } @@ -15356,7 +15352,7 @@ Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst, Diag(IdLoc, diag::err_redefinition_of_enumerator) << Id; else Diag(IdLoc, diag::err_redefinition) << Id; - notePreviousDefinition(PrevDecl->getLocation(), IdLoc); + notePreviousDefinition(PrevDecl, IdLoc); return nullptr; } } @@ -16052,8 +16048,10 @@ void Sema::ActOnModuleBegin(SourceLocation DirectiveLoc, Module *Mod) { // FIXME: Consider creating a child DeclContext to hold the entities // lexically within the module. if (getLangOpts().trackLocalOwningModule()) { - cast(CurContext)->setHidden(true); - cast(CurContext)->setLocalOwningModule(Mod); + for (auto *DC = CurContext; DC; DC = DC->getLexicalParent()) { + cast(DC)->setHidden(true); + cast(DC)->setLocalOwningModule(Mod); + } } } @@ -16086,9 +16084,13 @@ void Sema::ActOnModuleEnd(SourceLocation EomLoc, Module *Mod) { // Any further declarations are in whatever module we returned to. if (getLangOpts().trackLocalOwningModule()) { - cast(CurContext)->setLocalOwningModule(getCurrentModule()); - if (!getCurrentModule()) - cast(CurContext)->setHidden(false); + // The parser guarantees that this is the same context that we entered + // the module within. + for (auto *DC = CurContext; DC; DC = DC->getLexicalParent()) { + cast(DC)->setLocalOwningModule(getCurrentModule()); + if (!getCurrentModule()) + cast(DC)->setHidden(false); + } } } diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 3de792e4e406..32be26efa14f 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -5935,12 +5935,18 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, handleDLLAttr(S, D, Attr); break; case AttributeList::AT_Mips16: - handleSimpleAttributeWithExclusions(S, D, - Attr); + handleSimpleAttributeWithExclusions(S, D, Attr); break; case AttributeList::AT_NoMips16: handleSimpleAttribute(S, D, Attr); break; + case AttributeList::AT_MicroMips: + handleSimpleAttributeWithExclusions(S, D, Attr); + break; + case AttributeList::AT_NoMicroMips: + handleSimpleAttribute(S, D, Attr); + break; case AttributeList::AT_AMDGPUFlatWorkGroupSize: handleAMDGPUFlatWorkGroupSizeAttr(S, D, Attr); break; @@ -7252,6 +7258,12 @@ class DiagnoseUnguardedAvailability bool TraverseLambdaExpr(LambdaExpr *E) { return true; } + bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *PRE) { + if (PRE->isClassReceiver()) + DiagnoseDeclAvailability(PRE->getClassReceiver(), PRE->getReceiverLocation()); + return true; + } + bool VisitObjCMessageExpr(ObjCMessageExpr *Msg) { if (ObjCMethodDecl *D = Msg->getMethodDecl()) DiagnoseDeclAvailability( @@ -7381,6 +7393,9 @@ bool DiagnoseUnguardedAvailability::VisitTypeLoc(TypeLoc Ty) { const Type *TyPtr = Ty.getTypePtr(); SourceRange Range{Ty.getBeginLoc(), Ty.getEndLoc()}; + if (Range.isInvalid()) + return true; + if (const TagType *TT = dyn_cast(TyPtr)) { TagDecl *TD = TT->getDecl(); DiagnoseDeclAvailability(TD, Range); diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 04350831c681..678817f02996 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -1420,11 +1420,46 @@ bool Sema::hasVisibleDefaultArgument(const NamedDecl *D, Modules); } +template +static bool hasVisibleDeclarationImpl(Sema &S, const NamedDecl *D, + llvm::SmallVectorImpl *Modules, + Filter F) { + for (auto *Redecl : D->redecls()) { + auto *R = cast(Redecl); + if (!F(R)) + continue; + + if (S.isVisible(R)) + return true; + + if (Modules) { + Modules->push_back(R->getOwningModule()); + const auto &Merged = S.Context.getModulesWithMergedDefinition(R); + Modules->insert(Modules->end(), Merged.begin(), Merged.end()); + } + } + + return false; +} + +bool Sema::hasVisibleExplicitSpecialization( + const NamedDecl *D, llvm::SmallVectorImpl *Modules) { + return hasVisibleDeclarationImpl(*this, D, Modules, [](const NamedDecl *D) { + if (auto *RD = dyn_cast(D)) + return RD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization; + if (auto *FD = dyn_cast(D)) + return FD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization; + if (auto *VD = dyn_cast(D)) + return VD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization; + llvm_unreachable("unknown explicit specialization kind"); + }); +} + bool Sema::hasVisibleMemberSpecialization( const NamedDecl *D, llvm::SmallVectorImpl *Modules) { assert(isa(D->getDeclContext()) && "not a member specialization"); - for (auto *Redecl : D->redecls()) { + return hasVisibleDeclarationImpl(*this, D, Modules, [](const NamedDecl *D) { // If the specialization is declared at namespace scope, then it's a member // specialization declaration. If it's lexically inside the class // definition then it was instantiated. @@ -1432,19 +1467,8 @@ bool Sema::hasVisibleMemberSpecialization( // FIXME: This is a hack. There should be a better way to determine this. // FIXME: What about MS-style explicit specializations declared within a // class definition? - if (Redecl->getLexicalDeclContext()->isFileContext()) { - auto *NonConstR = const_cast(cast(Redecl)); - - if (isVisible(NonConstR)) - return true; - - if (Modules) { - Modules->push_back(getOwningModule(NonConstR)); - const auto &Merged = Context.getModulesWithMergedDefinition(NonConstR); - Modules->insert(Modules->end(), Merged.begin(), Merged.end()); - } - } - } + return D->getLexicalDeclContext()->isFileContext(); + }); return false; } @@ -1459,23 +1483,19 @@ bool Sema::hasVisibleMemberSpecialization( /// your module can see, including those later on in your module). bool LookupResult::isVisibleSlow(Sema &SemaRef, NamedDecl *D) { assert(D->isHidden() && "should not call this: not in slow case"); - Module *DeclModule = nullptr; - - if (SemaRef.getLangOpts().ModulesLocalVisibility) { - DeclModule = SemaRef.getOwningModule(D); - if (!DeclModule) { - assert(!D->isHidden() && "hidden decl not from a module"); - return true; - } - // If the owning module is visible, and the decl is not module private, - // then the decl is visible too. (Module private is ignored within the same - // top-level module.) - if ((!D->isFromASTFile() || !D->isModulePrivate()) && - (SemaRef.isModuleVisible(DeclModule) || - SemaRef.hasVisibleMergedDefinition(D))) - return true; - } + Module *DeclModule = SemaRef.getOwningModule(D); + assert(DeclModule && "hidden decl not from a module"); + + // If the owning module is visible, and the decl is not module private, + // then the decl is visible too. (Module private is ignored within the same + // top-level module.) + // FIXME: Check the owning module for module-private declarations rather than + // assuming "same AST file" is the same thing as "same module". + if ((!D->isFromASTFile() || !D->isModulePrivate()) && + (SemaRef.isModuleVisible(DeclModule) || + SemaRef.hasVisibleMergedDefinition(D))) + return true; // If this declaration is not at namespace scope nor module-private, // then it is visible if its lexical parent has a visible definition. @@ -1571,20 +1591,8 @@ static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D) { bool Sema::hasVisibleDeclarationSlow(const NamedDecl *D, llvm::SmallVectorImpl *Modules) { assert(!isVisible(D) && "not in slow case"); - - for (auto *Redecl : D->redecls()) { - auto *NonConstR = const_cast(cast(Redecl)); - if (isVisible(NonConstR)) - return true; - - if (Modules) { - Modules->push_back(getOwningModule(NonConstR)); - const auto &Merged = Context.getModulesWithMergedDefinition(NonConstR); - Modules->insert(Modules->end(), Merged.begin(), Merged.end()); - } - } - - return false; + return hasVisibleDeclarationImpl(*this, D, Modules, + [](const NamedDecl *) { return true; }); } NamedDecl *LookupResult::getAcceptableDeclSlow(NamedDecl *D) const { @@ -4957,6 +4965,14 @@ void Sema::diagnoseMissingImport(SourceLocation UseLoc, NamedDecl *Decl, MissingImportKind MIK, bool Recover) { assert(!Modules.empty()); + // Weed out duplicates from module list. + llvm::SmallVector UniqueModules; + llvm::SmallDenseSet UniqueModuleSet; + for (auto *M : Modules) + if (UniqueModuleSet.insert(M).second) + UniqueModules.push_back(M); + Modules = UniqueModules; + if (Modules.size() > 1) { std::string ModuleList; unsigned N = 0; @@ -4971,8 +4987,8 @@ void Sema::diagnoseMissingImport(SourceLocation UseLoc, NamedDecl *Decl, Diag(UseLoc, diag::err_module_unimported_use_multiple) << (int)MIK << Decl << ModuleList; - } else if (const FileEntry *E = - PP.getModuleHeaderToIncludeForDiagnostics(UseLoc, DeclLoc)) { + } else if (const FileEntry *E = PP.getModuleHeaderToIncludeForDiagnostics( + UseLoc, Modules[0], DeclLoc)) { // The right way to make the declaration visible is to include a header; // suggest doing so. // diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index a479d1027533..8cd7efbb1dba 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -7901,6 +7901,7 @@ bool Sema::CheckFunctionTemplateSpecialization( TemplateSpecializationKind TSK = SpecInfo->getTemplateSpecializationKind(); if (TSK == TSK_Undeclared || TSK == TSK_ImplicitInstantiation) { Specialization->setLocation(FD->getLocation()); + Specialization->setLexicalDeclContext(FD->getLexicalDeclContext()); // C++11 [dcl.constexpr]p1: An explicit specialization of a constexpr // function can differ from the template declaration with respect to // the constexpr specifier. @@ -7961,6 +7962,7 @@ bool Sema::CheckFunctionTemplateSpecialization( // FIXME: We need an update record for this AST mutation. Specialization->setDeletedAsWritten(false); } + // FIXME: We need an update record for this AST mutation. SpecInfo->setTemplateSpecializationKind(TSK_ExplicitSpecialization); MarkUnusedFileScopedDecl(Specialization); } @@ -9745,7 +9747,7 @@ class ExplicitSpecializationVisibilityChecker { IsHiddenExplicitSpecialization = Spec->getMemberSpecializationInfo() ? !S.hasVisibleMemberSpecialization(Spec, &Modules) - : !S.hasVisibleDeclaration(Spec); + : !S.hasVisibleExplicitSpecialization(Spec, &Modules); } else { checkInstantiated(Spec); } diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 03df6fde6c80..e7523ce2836d 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1540,8 +1540,7 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) { // DR1484 clarifies that the members of a local class are instantiated as part // of the instantiation of their enclosing entity. if (D->isCompleteDefinition() && D->isLocalClass()) { - Sema::SavePendingLocalImplicitInstantiationsRAII - SavedPendingLocalImplicitInstantiations(SemaRef); + Sema::LocalEagerInstantiationScope LocalInstantiations(SemaRef); SemaRef.InstantiateClass(D->getLocation(), Record, D, TemplateArgs, TSK_ImplicitInstantiation, @@ -1555,7 +1554,7 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) { // This class may have local implicit instantiations that need to be // performed within this scope. - SemaRef.PerformPendingInstantiations(/*LocalOnly=*/true); + LocalInstantiations.perform(); } SemaRef.DiagnoseUnusedNestedTypedefs(Record); @@ -3812,10 +3811,9 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, // while we're still within our own instantiation context. // This has to happen before LateTemplateParser below is called, so that // it marks vtables used in late parsed templates as used. - SavePendingLocalImplicitInstantiationsRAII - SavedPendingLocalImplicitInstantiations(*this); - SavePendingInstantiationsAndVTableUsesRAII - SavePendingInstantiationsAndVTableUses(*this, /*Enabled=*/Recursive); + GlobalEagerInstantiationScope GlobalInstantiations(*this, + /*Enabled=*/Recursive); + LocalEagerInstantiationScope LocalInstantiations(*this); // Call the LateTemplateParser callback if there is a need to late parse // a templated function definition. @@ -3942,20 +3940,9 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, // This class may have local implicit instantiations that need to be // instantiation within this scope. - PerformPendingInstantiations(/*LocalOnly=*/true); + LocalInstantiations.perform(); Scope.Exit(); - - if (Recursive) { - // Define any pending vtables. - DefineUsedVTables(); - - // Instantiate any pending implicit instantiations found during the - // instantiation of this template. - PerformPendingInstantiations(); - - // PendingInstantiations and VTableUses are restored through - // SavePendingInstantiationsAndVTableUses's destructor. - } + GlobalInstantiations.perform(); } VarTemplateSpecializationDecl *Sema::BuildVarTemplateInstantiation( @@ -4287,10 +4274,10 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation, // If we're performing recursive template instantiation, create our own // queue of pending implicit instantiations that we will instantiate // later, while we're still within our own instantiation context. - SavePendingInstantiationsAndVTableUsesRAII - SavePendingInstantiationsAndVTableUses(*this, /*Enabled=*/Recursive); - + GlobalEagerInstantiationScope GlobalInstantiations(*this, + /*Enabled=*/Recursive); LocalInstantiationScope Local(*this); + LocalEagerInstantiationScope LocalInstantiations(*this); // Enter the scope of this instantiation. We don't use // PushDeclContext because we don't have a scope. @@ -4303,21 +4290,9 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation, // This variable may have local implicit instantiations that need to be // instantiated within this scope. - PerformPendingInstantiations(/*LocalOnly=*/true); - + LocalInstantiations.perform(); Local.Exit(); - - if (Recursive) { - // Define any newly required vtables. - DefineUsedVTables(); - - // Instantiate any pending implicit instantiations found during the - // instantiation of this template. - PerformPendingInstantiations(); - - // PendingInstantiations and VTableUses are restored through - // SavePendingInstantiationsAndVTableUses's destructor. - } + GlobalInstantiations.perform(); } // Find actual definition @@ -4408,16 +4383,16 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation, // If we're performing recursive template instantiation, create our own // queue of pending implicit instantiations that we will instantiate later, // while we're still within our own instantiation context. - SavePendingLocalImplicitInstantiationsRAII - SavedPendingLocalImplicitInstantiations(*this); - SavePendingInstantiationsAndVTableUsesRAII - SavePendingInstantiationsAndVTableUses(*this, /*Enabled=*/Recursive); + GlobalEagerInstantiationScope GlobalInstantiations(*this, + /*Enabled=*/Recursive); // Enter the scope of this instantiation. We don't use // PushDeclContext because we don't have a scope. ContextRAII PreviousContext(*this, Var->getDeclContext()); LocalInstantiationScope Local(*this); + LocalEagerInstantiationScope LocalInstantiations(*this); + VarDecl *OldVar = Var; if (Def->isStaticDataMember() && !Def->isOutOfLine()) { // We're instantiating an inline static data member whose definition was @@ -4470,21 +4445,9 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation, // This variable may have local implicit instantiations that need to be // instantiated within this scope. - PerformPendingInstantiations(/*LocalOnly=*/true); - + LocalInstantiations.perform(); Local.Exit(); - - if (Recursive) { - // Define any newly required vtables. - DefineUsedVTables(); - - // Instantiate any pending implicit instantiations found during the - // instantiation of this template. - PerformPendingInstantiations(); - - // PendingInstantiations and VTableUses are restored through - // SavePendingInstantiationsAndVTableUses's destructor. - } + GlobalInstantiations.perform(); } void diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 3992179fabae..f8970744389b 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -3735,16 +3735,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // inner pointers. complainAboutMissingNullability = CAMN_InnerPointers; - auto isDependentNonPointerType = [](QualType T) -> bool { - // Note: This is intended to be the same check as Type::canHaveNullability - // except with all of the ambiguous cases being treated as 'false' rather - // than 'true'. - return T->isDependentType() && !T->isAnyPointerType() && - !T->isBlockPointerType() && !T->isMemberPointerType(); - }; - - if (T->canHaveNullability() && !T->getNullability(S.Context) && - !isDependentNonPointerType(T)) { + if (T->canHaveNullability(/*ResultIfUnknown*/false) && + !T->getNullability(S.Context)) { // Note that we allow but don't require nullability on dependent types. ++NumPointersRemaining; } @@ -3962,7 +3954,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // If the type itself could have nullability but does not, infer pointer // nullability and perform consistency checking. if (S.CodeSynthesisContexts.empty()) { - if (T->canHaveNullability() && !T->getNullability(S.Context)) { + if (T->canHaveNullability(/*ResultIfUnknown*/false) && + !T->getNullability(S.Context)) { if (isVaList(T)) { // Record that we've seen a pointer, but do nothing else. if (NumPointersRemaining > 0) @@ -5531,14 +5524,15 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type, addrSpace.setIsSigned(false); } llvm::APSInt max(addrSpace.getBitWidth()); - max = Qualifiers::MaxAddressSpace - LangAS::Count; + max = Qualifiers::MaxAddressSpace - LangAS::FirstTargetAddressSpace; if (addrSpace > max) { S.Diag(Attr.getLoc(), diag::err_attribute_address_space_too_high) << (unsigned)max.getZExtValue() << ASArgExpr->getSourceRange(); Attr.setInvalid(); return; } - ASIdx = static_cast(addrSpace.getZExtValue()) + LangAS::Count; + ASIdx = static_cast(addrSpace.getZExtValue()) + + LangAS::FirstTargetAddressSpace; } else { // The keyword-based type attributes imply which address space to use. switch (Attr.getKind()) { diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 5cabd0e6740d..55cb670f427e 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -2756,7 +2756,8 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { // If we've already loaded the decl, perform the updates when we finish // loading this block. if (Decl *D = GetExistingDecl(ID)) - PendingUpdateRecords.push_back(std::make_pair(ID, D)); + PendingUpdateRecords.push_back( + PendingUpdateRecord(ID, D, /*JustLoaded=*/false)); break; } @@ -3086,7 +3087,8 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { // If we've already loaded the decl, perform the updates when we finish // loading this block. if (Decl *D = GetExistingDecl(ID)) - PendingUpdateRecords.push_back(std::make_pair(ID, D)); + PendingUpdateRecords.push_back( + PendingUpdateRecord(ID, D, /*JustLoaded=*/false)); } break; } @@ -8956,7 +8958,7 @@ void ASTReader::finishPendingActions() { while (!PendingUpdateRecords.empty()) { auto Update = PendingUpdateRecords.pop_back_val(); ReadingKindTracker ReadingKind(Read_Decl, *this); - loadDeclUpdateRecords(Update.first, Update.second); + loadDeclUpdateRecords(Update); } } diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index e0304d22fe50..f3ee9078298e 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -3612,7 +3612,8 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { assert(Record.getIdx() == Record.size()); // Load any relevant update records. - PendingUpdateRecords.push_back(std::make_pair(ID, D)); + PendingUpdateRecords.push_back( + PendingUpdateRecord(ID, D, /*JustLoaded=*/true)); // Load the categories after recursive loading is finished. if (ObjCInterfaceDecl *Class = dyn_cast(D)) @@ -3657,20 +3658,24 @@ void ASTReader::PassInterestingDeclsToConsumer() { } } -void ASTReader::loadDeclUpdateRecords(serialization::DeclID ID, Decl *D) { +void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) { // The declaration may have been modified by files later in the chain. // If this is the case, read the record containing the updates from each file // and pass it to ASTDeclReader to make the modifications. + serialization::GlobalDeclID ID = Record.ID; + Decl *D = Record.D; ProcessingUpdatesRAIIObj ProcessingUpdates(*this); DeclUpdateOffsetsMap::iterator UpdI = DeclUpdateOffsets.find(ID); if (UpdI != DeclUpdateOffsets.end()) { auto UpdateOffsets = std::move(UpdI->second); DeclUpdateOffsets.erase(UpdI); - // FIXME: This call to isConsumerInterestedIn is not safe because - // we could be deserializing declarations at the moment. We should - // delay calling this in the same way as done in D30793. - bool WasInteresting = isConsumerInterestedIn(Context, D, false); + // Check if this decl was interesting to the consumer. If we just loaded + // the declaration, then we know it was interesting and we skip the call + // to isConsumerInterestedIn because it is unsafe to call in the + // current ASTReader state. + bool WasInteresting = + Record.JustLoaded || isConsumerInterestedIn(Context, D, false); for (auto &FileAndOffset : UpdateOffsets) { ModuleFile *F = FileAndOffset.first; uint64_t Offset = FileAndOffset.second; diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index b6c0cb2815fb..b3556371c9b8 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -2841,25 +2841,6 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) { "non-imported submodule?"); } -serialization::SubmoduleID -ASTWriter::inferSubmoduleIDFromLocation(SourceLocation Loc) { - if (Loc.isInvalid() || !WritingModule) - return 0; // No submodule - - // Find the module that owns this location. - ModuleMap &ModMap = PP->getHeaderSearchInfo().getModuleMap(); - Module *OwningMod - = ModMap.inferModuleFromLocation(FullSourceLoc(Loc,PP->getSourceManager())); - if (!OwningMod) - return 0; - - // Check whether this submodule is part of our own module. - if (WritingModule != OwningMod && !OwningMod->isSubModuleOf(WritingModule)) - return 0; - - return getSubmoduleID(OwningMod); -} - void ASTWriter::WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag, bool isModule) { llvm::SmallDenseMap diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index 812cd9e916d9..8fa64aa1b9d3 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -299,7 +299,7 @@ void ASTDeclWriter::VisitDecl(Decl *D) { Record.push_back(D->isTopLevelDeclInObjCContainer()); Record.push_back(D->getAccess()); Record.push_back(D->isModulePrivate()); - Record.push_back(Writer.inferSubmoduleIDFromLocation(D->getLocation())); + Record.push_back(Writer.getSubmoduleID(D->getOwningModule())); // If this declaration injected a name into a context different from its // lexical context, and that context is an imported namespace, we need to diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp index 2114033ba8b5..2c3169c0f8dd 100644 --- a/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -3448,14 +3448,12 @@ void BugReporter::FlushReport(BugReport *exampleReport, // the BugReporterVisitors may mark this bug as a false positive. assert(!bugReports.empty()); - MaxBugClassSize = - std::max(bugReports.size(), static_cast(MaxBugClassSize)); + MaxBugClassSize.updateMax(bugReports.size()); if (!generatePathDiagnostic(*D.get(), PD, bugReports)) return; - MaxValidBugClassSize = - std::max(bugReports.size(), static_cast(MaxValidBugClassSize)); + MaxValidBugClassSize.updateMax(bugReports.size()); // Examine the report and see if the last piece is in a header. Reset the // report location to the last piece in the main source file. diff --git a/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp index 0fe0f3a6ed58..c47edc7d2125 100644 --- a/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp +++ b/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp @@ -674,10 +674,8 @@ void AnalysisConsumer::HandleCode(Decl *D, AnalysisMode Mode, DisplayFunction(D, Mode, IMode); CFG *DeclCFG = Mgr->getCFG(D); - if (DeclCFG) { - unsigned CFGSize = DeclCFG->size(); - MaxCFGSize = MaxCFGSize < CFGSize ? CFGSize : MaxCFGSize; - } + if (DeclCFG) + MaxCFGSize.updateMax(DeclCFG->size()); BugReporter BR(*Mgr); diff --git a/test/CodeGen/address-space.c b/test/CodeGen/address-space.c index 5d57d5b6ebe5..35e3dbdcfa73 100644 --- a/test/CodeGen/address-space.c +++ b/test/CodeGen/address-space.c @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm < %s | FileCheck -check-prefixes=CHECK,GIZ %s // RUN: %clang_cc1 -triple amdgcn -emit-llvm < %s | FileCheck -check-prefixes=CHECK,PIZ %s -// RUN: %clang_cc1 -triple amdgcn---amdgiz -emit-llvm < %s | FileCheck -check-prefixes=CHeCK,GIZ %s +// RUN: %clang_cc1 -triple amdgcn---amdgiz -emit-llvm < %s | FileCheck -check-prefixes=CHECK,GIZ %s // CHECK: @foo = common addrspace(1) global int foo __attribute__((address_space(1))); @@ -40,8 +40,10 @@ typedef struct { } MyStruct; // CHECK-LABEL: define void @test4( -// CHECK: call void @llvm.memcpy.p0i8.p2i8 -// CHECK: call void @llvm.memcpy.p2i8.p0i8 +// GIZ: call void @llvm.memcpy.p0i8.p2i8 +// GIZ: call void @llvm.memcpy.p2i8.p0i8 +// PIZ: call void @llvm.memcpy.p4i8.p2i8 +// PIZ: call void @llvm.memcpy.p2i8.p4i8 void test4(MyStruct __attribute__((address_space(2))) *pPtr) { MyStruct s = pPtr[0]; pPtr[0] = s; diff --git a/test/CodeGen/micromips-attr.c b/test/CodeGen/micromips-attr.c new file mode 100644 index 000000000000..96ba774afc0f --- /dev/null +++ b/test/CodeGen/micromips-attr.c @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -triple mips-linux-gnu -emit-llvm -o - %s | FileCheck %s + +void __attribute__((micromips)) foo (void) {} + +// CHECK: define void @foo() [[MICROMIPS:#[0-9]+]] + +void __attribute__((nomicromips)) nofoo (void) {} + +// CHECK: define void @nofoo() [[NOMICROMIPS:#[0-9]+]] + +// CHECK: attributes [[MICROMIPS]] = { noinline nounwind {{.*}} "micromips" {{.*}} } +// CHECK: attributes [[NOMICROMIPS]] = { noinline nounwind {{.*}} "nomicromips" {{.*}} } diff --git a/test/CodeGen/wchar-size.c b/test/CodeGen/wchar-size.c new file mode 100644 index 000000000000..38da462d98cb --- /dev/null +++ b/test/CodeGen/wchar-size.c @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s -check-prefix=LONG-WCHAR +// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -emit-llvm -o - %s | FileCheck %s -check-prefix=SHORT-WCHAR +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -o - -fshort-wchar %s | FileCheck %s -check-prefix=SHORT-WCHAR +// Note: -fno-short-wchar implies the target default is used; so there is no +// need to test this separately here. + +// LONG-WCHAR: !{{[0-9]+}} = !{i32 {{[0-9]+}}, !"wchar_size", i32 4} +// SHORT-WCHAR: !{{[0-9]+}} = !{i32 {{[0-9]+}}, !"wchar_size", i32 2} diff --git a/test/CodeGenCUDA/flush-denormals.cu b/test/CodeGenCUDA/flush-denormals.cu index e528d7b102d4..94285f1f33ce 100644 --- a/test/CodeGenCUDA/flush-denormals.cu +++ b/test/CodeGenCUDA/flush-denormals.cu @@ -18,8 +18,8 @@ extern "C" __device__ void foo() {} // FTZ: attributes #0 = {{.*}} "nvptx-f32ftz"="true" // NOFTZ-NOT: attributes #0 = {{.*}} "nvptx-f32ftz" -// FTZ:!llvm.module.flags = !{[[MODFLAG:![0-9]+]]} +// FTZ:!llvm.module.flags = !{{{.*}}[[MODFLAG:![0-9]+]]} // FTZ:[[MODFLAG]] = !{i32 4, !"nvvm-reflect-ftz", i32 1} -// NOFTZ:!llvm.module.flags = !{[[MODFLAG:![0-9]+]]} +// NOFTZ:!llvm.module.flags = !{{{.*}}[[MODFLAG:![0-9]+]]} // NOFTZ:[[MODFLAG]] = !{i32 4, !"nvvm-reflect-ftz", i32 0} diff --git a/test/CodeGenCXX/amdgcn-automatic-variable.cpp b/test/CodeGenCXX/amdgcn-automatic-variable.cpp new file mode 100644 index 000000000000..aab720770d12 --- /dev/null +++ b/test/CodeGenCXX/amdgcn-automatic-variable.cpp @@ -0,0 +1,72 @@ +// RUN: %clang_cc1 -O0 -triple amdgcn---amdgiz -emit-llvm %s -o - | FileCheck %s + +// CHECK-LABEL: define void @_Z5func1Pi(i32* %x) +void func1(int *x) { + // CHECK: %[[x_addr:.*]] = alloca i32*{{.*}}addrspace(5) + // CHECK: store i32* %x, i32* addrspace(5)* %[[x_addr]] + // CHECK: %[[r0:.*]] = load i32*, i32* addrspace(5)* %[[x_addr]] + // CHECK: store i32 1, i32* %[[r0]] + *x = 1; +} + +// CHECK-LABEL: define void @_Z5func2v() +void func2(void) { + // CHECK: %lv1 = alloca i32, align 4, addrspace(5) + // CHECK: %lv2 = alloca i32, align 4, addrspace(5) + // CHECK: %la = alloca [100 x i32], align 4, addrspace(5) + // CHECK: %lp1 = alloca i32*, align 4, addrspace(5) + // CHECK: %lp2 = alloca i32*, align 4, addrspace(5) + // CHECK: %lvc = alloca i32, align 4, addrspace(5) + + // CHECK: %[[r0:.*]] = addrspacecast i32 addrspace(5)* %lv1 to i32* + // CHECK: store i32 1, i32* %[[r0]] + int lv1; + lv1 = 1; + // CHECK: %[[r1:.*]] = addrspacecast i32 addrspace(5)* %lv2 to i32* + // CHECK: store i32 2, i32* %[[r1]] + int lv2 = 2; + + // CHECK: %[[r2:.*]] = addrspacecast [100 x i32] addrspace(5)* %la to [100 x i32]* + // CHECK: %[[arrayidx:.*]] = getelementptr inbounds [100 x i32], [100 x i32]* %[[r2]], i64 0, i64 0 + // CHECK: store i32 3, i32* %[[arrayidx]], align 4 + int la[100]; + la[0] = 3; + + // CHECK: %[[r3:.*]] = addrspacecast i32* addrspace(5)* %lp1 to i32** + // CHECK: store i32* %[[r0]], i32** %[[r3]], align 4 + int *lp1 = &lv1; + + // CHECK: %[[r4:.*]] = addrspacecast i32* addrspace(5)* %lp2 to i32** + // CHECK: %[[arraydecay:.*]] = getelementptr inbounds [100 x i32], [100 x i32]* %[[r2]], i32 0, i32 0 + // CHECK: store i32* %[[arraydecay]], i32** %[[r4]], align 4 + int *lp2 = la; + + // CHECK: call void @_Z5func1Pi(i32* %[[r0]]) + func1(&lv1); + + // CHECK: %[[r5:.*]] = addrspacecast i32 addrspace(5)* %lvc to i32* + // CHECK: store i32 4, i32* %[[r5]] + // CHECK: store i32 4, i32* %[[r0]] + const int lvc = 4; + lv1 = lvc; +} + +void destroy(int x); + +class A { +int x; +public: + A():x(0) {} + ~A() { + destroy(x); + } +}; + +// CHECK-LABEL: define void @_Z5func3v +void func3() { + // CHECK: %[[a:.*]] = alloca %class.A, align 4, addrspace(5) + // CHECK: %[[r0:.*]] = addrspacecast %class.A addrspace(5)* %[[a]] to %class.A* + // CHECK: call void @_ZN1AC1Ev(%class.A* %[[r0]]) + // CHECK: call void @_ZN1AD1Ev(%class.A* %[[r0]]) + A a; +} diff --git a/test/CodeGenCXX/strict-vtable-pointers.cpp b/test/CodeGenCXX/strict-vtable-pointers.cpp index 21f85b1c5772..928817bfb1f5 100644 --- a/test/CodeGenCXX/strict-vtable-pointers.cpp +++ b/test/CodeGenCXX/strict-vtable-pointers.cpp @@ -211,7 +211,7 @@ struct DynamicFromStatic; // CHECK-DTORS-LABEL: {{^}}} -// CHECK-LINK-REQ: !llvm.module.flags = !{![[FIRST:.*]], ![[SEC:.*]]{{.*}}} +// CHECK-LINK-REQ: !llvm.module.flags = !{![[FIRST:[0-9]+]], ![[SEC:[0-9]+]]{{.*}}} // CHECK-LINK-REQ: ![[FIRST]] = !{i32 1, !"StrictVTablePointers", i32 1} // CHECK-LINK-REQ: ![[SEC]] = !{i32 3, !"StrictVTablePointersRequirement", ![[META:.*]]} diff --git a/test/CodeGenOpenCL/amdgcn-automatic-variable.cl b/test/CodeGenOpenCL/amdgcn-automatic-variable.cl new file mode 100644 index 000000000000..29309567ec71 --- /dev/null +++ b/test/CodeGenOpenCL/amdgcn-automatic-variable.cl @@ -0,0 +1,60 @@ +// RUN: %clang_cc1 -O0 -cl-std=CL1.2 -triple amdgcn---amdgizcl -emit-llvm %s -o - | FileCheck -check-prefixes=CHECK,CL12 %s +// RUN: %clang_cc1 -O0 -cl-std=CL2.0 -triple amdgcn---amdgizcl -emit-llvm %s -o - | FileCheck -check-prefixes=CHECK,CL20 %s + +// CL12-LABEL: define void @func1(i32 addrspace(5)* %x) +// CL20-LABEL: define void @func1(i32* %x) +void func1(int *x) { + // CL12: %[[x_addr:.*]] = alloca i32 addrspace(5)*{{.*}}addrspace(5) + // CL12: store i32 addrspace(5)* %x, i32 addrspace(5)* addrspace(5)* %[[x_addr]] + // CL12: %[[r0:.*]] = load i32 addrspace(5)*, i32 addrspace(5)* addrspace(5)* %[[x_addr]] + // CL12: store i32 1, i32 addrspace(5)* %[[r0]] + // CL20: %[[x_addr:.*]] = alloca i32*{{.*}}addrspace(5) + // CL20: store i32* %x, i32* addrspace(5)* %[[x_addr]] + // CL20: %[[r0:.*]] = load i32*, i32* addrspace(5)* %[[x_addr]] + // CL20: store i32 1, i32* %[[r0]] + *x = 1; +} + +// CHECK-LABEL: define void @func2() +void func2(void) { + // CHECK: %lv1 = alloca i32, align 4, addrspace(5) + // CHECK: %lv2 = alloca i32, align 4, addrspace(5) + // CHECK: %la = alloca [100 x i32], align 4, addrspace(5) + // CL12: %lp1 = alloca i32 addrspace(5)*, align 4, addrspace(5) + // CL12: %lp2 = alloca i32 addrspace(5)*, align 4, addrspace(5) + // CL20: %lp1 = alloca i32*, align 4, addrspace(5) + // CL20: %lp2 = alloca i32*, align 4, addrspace(5) + // CHECK: %lvc = alloca i32, align 4, addrspace(5) + + // CHECK: store i32 1, i32 addrspace(5)* %lv1 + int lv1; + lv1 = 1; + // CHECK: store i32 2, i32 addrspace(5)* %lv2 + int lv2 = 2; + + // CHECK: %[[arrayidx:.*]] = getelementptr inbounds [100 x i32], [100 x i32] addrspace(5)* %la, i64 0, i64 0 + // CHECK: store i32 3, i32 addrspace(5)* %[[arrayidx]], align 4 + int la[100]; + la[0] = 3; + + // CL12: store i32 addrspace(5)* %lv1, i32 addrspace(5)* addrspace(5)* %lp1, align 4 + // CL20: %[[r0:.*]] = addrspacecast i32 addrspace(5)* %lv1 to i32* + // CL20: store i32* %[[r0]], i32* addrspace(5)* %lp1, align 4 + int *lp1 = &lv1; + + // CHECK: %[[arraydecay:.*]] = getelementptr inbounds [100 x i32], [100 x i32] addrspace(5)* %la, i32 0, i32 0 + // CL12: store i32 addrspace(5)* %[[arraydecay]], i32 addrspace(5)* addrspace(5)* %lp2, align 4 + // CL20: %[[r1:.*]] = addrspacecast i32 addrspace(5)* %[[arraydecay]] to i32* + // CL20: store i32* %[[r1]], i32* addrspace(5)* %lp2, align 4 + int *lp2 = la; + + // CL12: call void @func1(i32 addrspace(5)* %lv1) + // CL20: %[[r2:.*]] = addrspacecast i32 addrspace(5)* %lv1 to i32* + // CL20: call void @func1(i32* %[[r2]]) + func1(&lv1); + + // CHECK: store i32 4, i32 addrspace(5)* %lvc + // CHECK: store i32 4, i32 addrspace(5)* %lv1 + const int lvc = 4; + lv1 = lvc; +} diff --git a/test/CodeGenOpenCL/amdgpu-alignment.cl b/test/CodeGenOpenCL/amdgpu-alignment.cl index 35a8342eec01..714e7240f539 100644 --- a/test/CodeGenOpenCL/amdgpu-alignment.cl +++ b/test/CodeGenOpenCL/amdgpu-alignment.cl @@ -1,5 +1,5 @@ // REQUIRES: amdgpu-registered-target -// RUN: %clang_cc1 -triple amdgcn-unknown-unknown -S -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple amdgcn-unknown-unknown-opencl -S -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s #pragma OPENCL EXTENSION cl_khr_fp64 : enable #pragma OPENCL EXTENSION cl_khr_fp16 : enable diff --git a/test/CodeGenOpenCL/amdgpu-debug-info-pointer-address-space.cl b/test/CodeGenOpenCL/amdgpu-debug-info-pointer-address-space.cl index 7baee5eee391..061ce2cca2fc 100644 --- a/test/CodeGenOpenCL/amdgpu-debug-info-pointer-address-space.cl +++ b/test/CodeGenOpenCL/amdgpu-debug-info-pointer-address-space.cl @@ -1,4 +1,4 @@ -// RUN: %clang -cl-std=CL2.0 -emit-llvm -g -O0 -S -target amdgcn-amd-amdhsa -mcpu=fiji -o - %s | FileCheck %s +// RUN: %clang -cl-std=CL2.0 -emit-llvm -g -O0 -S -target amdgcn-amd-amdhsa-opencl -mcpu=fiji -o - %s | FileCheck %s // CHECK-DAG: ![[DWARF_ADDRESS_SPACE_NONE:[0-9]+]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !{{[0-9]+}}, size: {{[0-9]+}}) // CHECK-DAG: ![[DWARF_ADDRESS_SPACE_LOCAL:[0-9]+]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !{{[0-9]+}}, size: {{[0-9]+}}, dwarfAddressSpace: 2) diff --git a/test/CodeGenOpenCL/amdgpu-debug-info-variable-expression.cl b/test/CodeGenOpenCL/amdgpu-debug-info-variable-expression.cl index c0a4c21ce760..8cf086bf8dcc 100644 --- a/test/CodeGenOpenCL/amdgpu-debug-info-variable-expression.cl +++ b/test/CodeGenOpenCL/amdgpu-debug-info-variable-expression.cl @@ -1,4 +1,4 @@ -// RUN: %clang -cl-std=CL2.0 -emit-llvm -g -O0 -S -target amdgcn-amd-amdhsa -mcpu=fiji -o - %s | FileCheck %s +// RUN: %clang -cl-std=CL2.0 -emit-llvm -g -O0 -S -target amdgcn-amd-amdhsa-opencl -mcpu=fiji -o - %s | FileCheck %s // CHECK-DAG: ![[LOCAL:[0-9]+]] = !DIExpression(DW_OP_constu, 2, DW_OP_swap, DW_OP_xderef) // CHECK-DAG: ![[PRIVATE:[0-9]+]] = !DIExpression(DW_OP_constu, 1, DW_OP_swap, DW_OP_xderef) diff --git a/test/CodeGenOpenCL/amdgpu-nullptr.cl b/test/CodeGenOpenCL/amdgpu-nullptr.cl index 37c7469aa180..3e54cd5c34a0 100644 --- a/test/CodeGenOpenCL/amdgpu-nullptr.cl +++ b/test/CodeGenOpenCL/amdgpu-nullptr.cl @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 %s -cl-std=CL2.0 -include opencl-c.h -triple amdgcn -emit-llvm -o - | FileCheck %s -// RUN: %clang_cc1 %s -O0 -cl-std=CL2.0 -include opencl-c.h -triple amdgcn -emit-llvm -o - | FileCheck --check-prefix=NOOPT %s +// RUN: %clang_cc1 %s -cl-std=CL2.0 -include opencl-c.h -triple amdgcn---opencl -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -O0 -cl-std=CL2.0 -include opencl-c.h -triple amdgcn---opencl -emit-llvm -o - | FileCheck --check-prefix=NOOPT %s typedef struct { private char *p1; diff --git a/test/CodeGenOpenCL/builtins-amdgcn.cl b/test/CodeGenOpenCL/builtins-amdgcn.cl index a19ce2f1ed59..fdbae9b531c1 100644 --- a/test/CodeGenOpenCL/builtins-amdgcn.cl +++ b/test/CodeGenOpenCL/builtins-amdgcn.cl @@ -1,5 +1,5 @@ // REQUIRES: amdgpu-registered-target -// RUN: %clang_cc1 -triple amdgcn-unknown-unknown -S -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple amdgcn-unknown-unknown-opencl -S -emit-llvm -o - %s | FileCheck %s #pragma OPENCL EXTENSION cl_khr_fp64 : enable diff --git a/test/CodeGenOpenCL/byval.cl b/test/CodeGenOpenCL/byval.cl index 1a8105c5207f..a7c5adfb79d6 100644 --- a/test/CodeGenOpenCL/byval.cl +++ b/test/CodeGenOpenCL/byval.cl @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -o - -triple amdgcn %s | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -o - -triple amdgcn---opencl %s | FileCheck %s // RUN: %clang_cc1 -emit-llvm -o - -triple amdgcn---amdgizcl %s | FileCheck %s -check-prefix=AMDGIZ struct A { diff --git a/test/CodeGenOpenCL/size_t.cl b/test/CodeGenOpenCL/size_t.cl index ed941e01852d..20f29fe1cd41 100644 --- a/test/CodeGenOpenCL/size_t.cl +++ b/test/CodeGenOpenCL/size_t.cl @@ -1,6 +1,6 @@ // RUN: %clang_cc1 %s -cl-std=CL2.0 -finclude-default-header -emit-llvm -O0 -triple spir-unknown-unknown -o - | FileCheck --check-prefix=SZ32 %s // RUN: %clang_cc1 %s -cl-std=CL2.0 -finclude-default-header -emit-llvm -O0 -triple spir64-unknown-unknown -o - | FileCheck --check-prefix=SZ64 --check-prefix=SZ64ONLY %s -// RUN: %clang_cc1 %s -cl-std=CL2.0 -finclude-default-header -emit-llvm -O0 -triple amdgcn-- -o - | FileCheck --check-prefix=SZ64 --check-prefix=AMDONLY %s +// RUN: %clang_cc1 %s -cl-std=CL2.0 -finclude-default-header -emit-llvm -O0 -triple amdgcn---opencl -o - | FileCheck --check-prefix=SZ64 --check-prefix=AMDONLY %s //SZ32: define{{.*}} i32 @test_ptrtoint_private(i8* %x) //SZ32: ptrtoint i8* %{{.*}} to i32 diff --git a/test/Index/Core/external-source-symbol-attr.m b/test/Index/Core/external-source-symbol-attr.m index 49a075fc74e0..cdc52966977d 100644 --- a/test/Index/Core/external-source-symbol-attr.m +++ b/test/Index/Core/external-source-symbol-attr.m @@ -4,6 +4,10 @@ #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)) +// Forward declarations should not affect module namespacing below +@class I1; +@class I2; + // This should not be indexed. GEN_DECL("some_module") @interface I1 diff --git a/test/Index/Core/index-dependent-source.cpp b/test/Index/Core/index-dependent-source.cpp index 8c097b935a37..59c6286cd3dd 100644 --- a/test/Index/Core/index-dependent-source.cpp +++ b/test/Index/Core/index-dependent-source.cpp @@ -141,3 +141,20 @@ void undefinedTemplateLookup2(UserOfUndefinedTemplateClass &x) { x.lookup; typename UserOfUndefinedTemplateClass::Type y; } + +template struct Dropper; + +template struct Trait; + +template +struct Recurse : Trait::Type> { }; + +template +struct Trait : Recurse { +}; + +template +void infiniteTraitRecursion(Trait &t) { +// Shouldn't crash! + t.lookup; +} diff --git a/test/Index/Core/index-source.cpp b/test/Index/Core/index-source.cpp index 9248e86ff697..8b049314ffbe 100644 --- a/test/Index/Core/index-source.cpp +++ b/test/Index/Core/index-source.cpp @@ -1,7 +1,7 @@ // RUN: c-index-test core -print-source-symbols -- %s -std=c++14 -target x86_64-apple-macosx10.7 | FileCheck %s // CHECK: [[@LINE+1]]:7 | class/C++ | Cls | [[Cls_USR:.*]] | | Def | rel: 0 -class Cls { +class Cls { public: // CHECK: [[@LINE+3]]:3 | constructor/C++ | Cls | c:@S@Cls@F@Cls#I# | __ZN3ClsC1Ei | Decl,RelChild | rel: 1 // CHECK-NEXT: RelChild | Cls | c:@S@Cls // CHECK: [[@LINE+1]]:3 | class/C++ | Cls | c:@S@Cls | | Ref,RelCont | rel: 1 @@ -339,3 +339,97 @@ void ::ns::inner::func() { // CHECK: [[@LINE-1]]:3 | namespace/C++ | ns | c:@N@ns | | Ref,RelCont | rel: 1 // CHECK: [[@LINE-2]]:7 | namespace-alias/C++ | innerAlias | c:@N@ns@NA@innerAlias | | Ref,RelCont | rel: 1 } + +void innerUsingNamespace() { + using namespace ns; +// CHECK: [[@LINE-1]]:19 | namespace/C++ | ns | c:@N@ns | | Ref,RelCont | rel: 1 + { + using namespace ns::innerAlias; +// CHECK: [[@LINE-1]]:25 | namespace-alias/C++ | innerAlias | c:@N@ns@NA@innerAlias | | Ref,RelCont | rel: 1 +// CHECK: [[@LINE-2]]:21 | namespace/C++ | ns | c:@N@ns | | Ref,RelCont | rel: 1 +// CHECK-NOT: [[@LINE-3]]:21 + } +} + +void indexDefaultValueInDefn(Cls cls = Cls(gvi), Record param = Record()) { +// CHECK: [[@LINE-1]]:40 | class/C++ | Cls | c:@S@Cls | | Ref,RelCont | rel: 1 +// CHECK: [[@LINE-2]]:44 | variable/C | gvi | c:@gvi | _gvi | Ref,Read,RelCont | rel: 1 +// CHECK-NOT: [[@LINE-3]]:44 +// CHECK: [[@LINE-4]]:65 | struct/C++ | Record | c:@S@Record | | Ref,RelCont | rel: 1 +// CHECK-NOT: [[@LINE-5]]:65 +} + +template