diff options
author | Pascal Stumpf <pascal@cvs.openbsd.org> | 2016-09-03 22:46:59 +0000 |
---|---|---|
committer | Pascal Stumpf <pascal@cvs.openbsd.org> | 2016-09-03 22:46:59 +0000 |
commit | 0fc2cd820c1f7bd4b47498f8319783cf0d02d123 (patch) | |
tree | 061fac75f5f69f89ab2ff0fbc2b0d8130fb5b41e /gnu/llvm/tools/clang | |
parent | 622d415bb6e3673b59ebf4f59e5499c10d22cd95 (diff) |
Use the space freed up by sparc and zaurus to import LLVM.
ok hackroom@
Diffstat (limited to 'gnu/llvm/tools/clang')
-rw-r--r-- | gnu/llvm/tools/clang/include/clang/Sema/Sema.h | 1908 | ||||
-rw-r--r-- | gnu/llvm/tools/clang/lib/Sema/SemaChecking.cpp | 3134 | ||||
-rw-r--r-- | gnu/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp | 1513 |
3 files changed, 1240 insertions, 5315 deletions
diff --git a/gnu/llvm/tools/clang/include/clang/Sema/Sema.h b/gnu/llvm/tools/clang/include/clang/Sema/Sema.h index 63d078498fe..29aa642a9ab 100644 --- a/gnu/llvm/tools/clang/include/clang/Sema/Sema.h +++ b/gnu/llvm/tools/clang/include/clang/Sema/Sema.h @@ -16,31 +16,26 @@ #define LLVM_CLANG_SEMA_SEMA_H #include "clang/AST/Attr.h" -#include "clang/AST/Availability.h" #include "clang/AST/DeclarationName.h" -#include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/ExternalASTSource.h" -#include "clang/AST/LocInfoType.h" #include "clang/AST/MangleNumberingContext.h" #include "clang/AST/NSAPI.h" #include "clang/AST/PrettyPrinter.h" #include "clang/AST/TypeLoc.h" -#include "clang/AST/TypeOrdering.h" #include "clang/Basic/ExpressionTraits.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/Module.h" #include "clang/Basic/OpenMPKinds.h" -#include "clang/Basic/PragmaKinds.h" #include "clang/Basic/Specifiers.h" #include "clang/Basic/TemplateKinds.h" #include "clang/Basic/TypeTraits.h" #include "clang/Sema/AnalysisBasedWarnings.h" -#include "clang/Sema/CleanupInfo.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/ExternalSemaSource.h" #include "clang/Sema/IdentifierResolver.h" +#include "clang/Sema/LocInfoType.h" #include "clang/Sema/ObjCMethodList.h" #include "clang/Sema/Ownership.h" #include "clang/Sema/Scope.h" @@ -75,7 +70,6 @@ namespace clang { class ASTWriter; class ArrayType; class AttributeList; - class BindingDecl; class BlockDecl; class CapturedDecl; class CXXBasePath; @@ -114,13 +108,13 @@ namespace clang { class EnumConstantDecl; class Expr; class ExtVectorType; + class ExternalSemaSource; class FormatAttr; class FriendDecl; class FunctionDecl; class FunctionProtoType; class FunctionTemplateDecl; class ImplicitConversionSequence; - typedef MutableArrayRef<ImplicitConversionSequence> ConversionSequenceList; class InitListExpr; class InitializationKind; class InitializationSequence; @@ -150,8 +144,6 @@ namespace clang { class ObjCPropertyDecl; class ObjCProtocolDecl; class OMPThreadPrivateDecl; - class OMPDeclareReductionDecl; - class OMPDeclareSimdDecl; class OMPClause; struct OverloadCandidate; class OverloadCandidateSet; @@ -322,28 +314,50 @@ public: /// This is used as part of a hack to omit that class from ADL results. DeclarationName VAListTagName; + /// PackContext - Manages the stack for \#pragma pack. An alignment + /// of 0 indicates default alignment. + void *PackContext; // Really a "PragmaPackStack*" + bool MSStructPragmaOn; // True when \#pragma ms_struct on /// \brief Controls member pointer representation format under the MS ABI. LangOptions::PragmaMSPointersToMembersKind MSPointerToMemberRepresentationMethod; + enum PragmaVtorDispKind { + PVDK_Push, ///< #pragma vtordisp(push, mode) + PVDK_Set, ///< #pragma vtordisp(mode) + PVDK_Pop, ///< #pragma vtordisp(pop) + PVDK_Reset ///< #pragma vtordisp() + }; + + enum PragmaMsStackAction { + PSK_Reset, // #pragma () + PSK_Set, // #pragma ("name") + PSK_Push, // #pragma (push[, id]) + PSK_Push_Set, // #pragma (push[, id], "name") + PSK_Pop, // #pragma (pop[, id]) + PSK_Pop_Set, // #pragma (pop[, id], "name") + }; + + /// \brief Whether to insert vtordisps prior to virtual bases in the Microsoft + /// C++ ABI. Possible values are 0, 1, and 2, which mean: + /// + /// 0: Suppress all vtordisps + /// 1: Insert vtordisps in the presence of vbase overrides and non-trivial + /// structors + /// 2: Always insert vtordisps to support RTTI on partially constructed + /// objects + /// + /// The stack always has at least one element in it. + SmallVector<MSVtorDispAttr::Mode, 2> VtorDispModeStack; + /// Stack of active SEH __finally scopes. Can be empty. SmallVector<Scope*, 2> CurrentSEHFinally; /// \brief Source location for newly created implicit MSInheritanceAttrs SourceLocation ImplicitMSInheritanceAttrLoc; - enum PragmaMsStackAction { - PSK_Reset = 0x0, // #pragma () - PSK_Set = 0x1, // #pragma (value) - PSK_Push = 0x2, // #pragma (push[, id]) - PSK_Pop = 0x4, // #pragma (pop[, id]) - PSK_Show = 0x8, // #pragma (show) -- only for "pack"! - PSK_Push_Set = PSK_Push | PSK_Set, // #pragma (push[, id], value) - PSK_Pop_Set = PSK_Pop | PSK_Set, // #pragma (pop[, id], value) - }; - template<typename ValueType> struct PragmaStack { struct Slot { @@ -360,71 +374,19 @@ public: PragmaMsStackAction Action, llvm::StringRef StackSlotLabel, ValueType Value); - - // MSVC seems to add artificial slots to #pragma stacks on entering a C++ - // method body to restore the stacks on exit, so it works like this: - // - // struct S { - // #pragma <name>(push, InternalPragmaSlot, <current_pragma_value>) - // void Method {} - // #pragma <name>(pop, InternalPragmaSlot) - // }; - // - // It works even with #pragma vtordisp, although MSVC doesn't support - // #pragma vtordisp(push [, id], n) - // syntax. - // - // Push / pop a named sentinel slot. - void SentinelAction(PragmaMsStackAction Action, StringRef Label) { - assert((Action == PSK_Push || Action == PSK_Pop) && - "Can only push / pop #pragma stack sentinels!"); - Act(CurrentPragmaLocation, Action, Label, CurrentValue); - } - - // Constructors. - explicit PragmaStack(const ValueType &Default) - : DefaultValue(Default), CurrentValue(Default) {} - + explicit PragmaStack(const ValueType &Value) + : CurrentValue(Value) {} SmallVector<Slot, 2> Stack; - ValueType DefaultValue; // Value used for PSK_Reset action. ValueType CurrentValue; SourceLocation CurrentPragmaLocation; }; // FIXME: We should serialize / deserialize these if they occur in a PCH (but // we shouldn't do so if they're in a module). - - /// \brief Whether to insert vtordisps prior to virtual bases in the Microsoft - /// C++ ABI. Possible values are 0, 1, and 2, which mean: - /// - /// 0: Suppress all vtordisps - /// 1: Insert vtordisps in the presence of vbase overrides and non-trivial - /// structors - /// 2: Always insert vtordisps to support RTTI on partially constructed - /// objects - PragmaStack<MSVtorDispAttr::Mode> VtorDispStack; - // #pragma pack. - // Sentinel to represent when the stack is set to mac68k alignment. - static const unsigned kMac68kAlignmentSentinel = ~0U; - PragmaStack<unsigned> PackStack; - // Segment #pragmas. PragmaStack<StringLiteral *> DataSegStack; PragmaStack<StringLiteral *> BSSSegStack; PragmaStack<StringLiteral *> ConstSegStack; PragmaStack<StringLiteral *> CodeSegStack; - // RAII object to push / pop sentinel slots for all MS #pragma stacks. - // Actions should be performed only if we enter / exit a C++ method body. - class PragmaStackSentinelRAII { - public: - PragmaStackSentinelRAII(Sema &S, StringRef SlotLabel, bool ShouldAct); - ~PragmaStackSentinelRAII(); - - private: - Sema &S; - StringRef SlotLabel; - bool ShouldAct; - }; - /// A mapping that describes the nullability we've seen in each header file. FileNullabilityMap NullabilityMap; @@ -446,8 +408,9 @@ public: /// if Sema is already doing so, which would cause infinite recursions. bool IsBuildingRecoveryCallExpr; - /// Used to control the generation of ExprWithCleanups. - CleanupInfo Cleanup; + /// ExprNeedsCleanups - True if the current evaluation context + /// requires cleanups to be run at its conclusion. + bool ExprNeedsCleanups; /// ExprCleanupObjects - This is the stack of objects requiring /// cleanup that are created by the current full expression. The @@ -457,9 +420,9 @@ public: /// \brief Store a list of either DeclRefExprs or MemberExprs /// that contain a reference to a variable (constant) that may or may not /// be odr-used in this Expr, and we won't know until all lvalue-to-rvalue - /// and discarded value conversions have been applied to all subexpressions - /// of the enclosing full expression. This is cleared at the end of each - /// full expression. + /// and discarded value conversions have been applied to all subexpressions + /// of the enclosing full expression. This is cleared at the end of each + /// full expression. llvm::SmallPtrSet<Expr*, 2> MaybeODRUseExprs; /// \brief Stack containing information about each of the nested @@ -553,8 +516,7 @@ public: SmallVector<std::pair<CXXMethodDecl*, const FunctionProtoType*>, 2> DelayedDefaultedMemberExceptionSpecs; - typedef llvm::MapVector<const FunctionDecl *, - std::unique_ptr<LateParsedTemplate>> + typedef llvm::MapVector<const FunctionDecl *, LateParsedTemplate *> LateParsedTemplateMapT; LateParsedTemplateMapT LateParsedTemplateMap; @@ -673,15 +635,15 @@ public: class SynthesizedFunctionScope { Sema &S; Sema::ContextRAII SavedContext; - + public: SynthesizedFunctionScope(Sema &S, DeclContext *DC) - : S(S), SavedContext(S, DC) + : S(S), SavedContext(S, DC) { S.PushFunctionScope(); S.PushExpressionEvaluationContext(Sema::PotentiallyEvaluated); } - + ~SynthesizedFunctionScope() { S.PopExpressionEvaluationContext(); S.PopFunctionScopeInfo(); @@ -724,14 +686,6 @@ public: /// standard library. LazyDeclPtr StdBadAlloc; - /// \brief The C++ "std::align_val_t" enum class, which is defined by the C++ - /// standard library. - LazyDeclPtr StdAlignValT; - - /// \brief The C++ "std::experimental" namespace, where the experimental parts - /// of the standard library resides. - NamespaceDecl *StdExperimentalNamespaceCache; - /// \brief The C++ "std::initializer_list" template, which is defined in /// \<initializer_list>. ClassTemplateDecl *StdInitializerList; @@ -790,12 +744,15 @@ public: /// \brief will hold 'respondsToSelector:' Selector RespondsToSelectorSel; + /// \brief counter for internal MS Asm label names. + unsigned MSAsmLabelNameCounter; + /// A flag to remember whether the implicit forms of operator new and delete /// have been declared. bool GlobalNewDeleteDeclared; /// A flag to indicate that we're in a context that permits abstract - /// references to fields. This is really a + /// references to fields. This is really a bool AllowAbstractFieldReference; /// \brief Describes how the expressions currently being parsed are @@ -808,17 +765,6 @@ public: /// run time. Unevaluated, - /// \brief The current expression occurs within a braced-init-list within - /// an unevaluated operand. This is mostly like a regular unevaluated - /// context, except that we still instantiate constexpr functions that are - /// referenced here so that we can perform narrowing checks correctly. - UnevaluatedList, - - /// \brief The current expression occurs within a discarded statement. - /// This behaves largely similarly to an unevaluated operand in preventing - /// definitions from being required, but not in other ways. - DiscardedStatement, - /// \brief The current expression occurs within an unevaluated /// operand that unconditionally permits abstract references to /// fields, such as a SIZE operator in MS-style inline assembly. @@ -852,7 +798,7 @@ public: ExpressionEvaluationContext Context; /// \brief Whether the enclosing context needed a cleanup. - CleanupInfo ParentCleanup; + bool ParentNeedsCleanups; /// \brief Whether we are in a decltype expression. bool IsDecltype; @@ -881,7 +827,7 @@ public: /// /// This mangling information is allocated lazily, since most contexts /// do not have lambda expressions or block literals. - std::unique_ptr<MangleNumberingContext> MangleNumbering; + IntrusiveRefCntPtr<MangleNumberingContext> MangleNumbering; /// \brief If we are processing a decltype type, a set of call expressions /// for which we have deferred checking the completeness of the return type. @@ -893,10 +839,10 @@ public: ExpressionEvaluationContextRecord(ExpressionEvaluationContext Context, unsigned NumCleanupObjects, - CleanupInfo ParentCleanup, + bool ParentNeedsCleanups, Decl *ManglingContextDecl, bool IsDecltype) - : Context(Context), ParentCleanup(ParentCleanup), + : Context(Context), ParentNeedsCleanups(ParentNeedsCleanups), IsDecltype(IsDecltype), NumCleanupObjects(NumCleanupObjects), NumTypos(0), ManglingContextDecl(ManglingContextDecl), MangleNumbering() { } @@ -906,8 +852,7 @@ public: MangleNumberingContext &getMangleNumberingContext(ASTContext &Ctx); bool isUnevaluated() const { - return Context == Unevaluated || Context == UnevaluatedAbstract || - Context == UnevaluatedList; + return Context == Unevaluated || Context == UnevaluatedAbstract; } }; @@ -994,7 +939,7 @@ public: /// UndefinedInternals - all the used, undefined objects which require a /// definition in this translation unit. - llvm::MapVector<NamedDecl *, SourceLocation> UndefinedButUsed; + llvm::DenseMap<NamedDecl *, SourceLocation> UndefinedButUsed; /// Obtain a sorted list of functions that are undefined but ODR-used. void getUndefinedButUsed( @@ -1039,7 +984,6 @@ public: llvm::SmallSet<SpecialMemberDecl, 4> SpecialMembersBeingDeclared; void ReadMethodPool(Selector Sel); - void updateOutOfDateSelector(Selector Sel); /// Private Helper predicate to check for 'self'. bool isSelfExpr(Expr *RExpr); @@ -1064,6 +1008,24 @@ public: bool OldFPContractState : 1; }; + /// Records and restores the vtordisp state on entry/exit of C++ method body. + class VtorDispStackRAII { + public: + VtorDispStackRAII(Sema &S, bool ShouldSaveAndRestore) + : S(S), ShouldSaveAndRestore(ShouldSaveAndRestore), OldVtorDispStack() { + if (ShouldSaveAndRestore) + OldVtorDispStack = S.VtorDispModeStack; + } + ~VtorDispStackRAII() { + if (ShouldSaveAndRestore) + S.VtorDispModeStack = OldVtorDispStack; + } + private: + Sema &S; + bool ShouldSaveAndRestore; + SmallVector<MSVtorDispAttr::Mode, 2> OldVtorDispStack; + }; + void addImplicitTypedef(StringRef Name, QualType T); public: @@ -1193,7 +1155,7 @@ public: /// is during Parsing. Currently it is used to pass on the depth /// when parsing generic lambda 'auto' parameters. void RecordParsingTemplateParameterDepth(unsigned Depth); - + void PushCapturedRegionScope(Scope *RegionScope, CapturedDecl *CD, RecordDecl *RD, CapturedRegionKind K); @@ -1205,11 +1167,11 @@ public: sema::FunctionScopeInfo *getCurFunction() const { return FunctionScopes.back(); } - + sema::FunctionScopeInfo *getEnclosingFunction() const { if (FunctionScopes.empty()) return nullptr; - + for (int e = FunctionScopes.size()-1; e >= 0; --e) { if (isa<sema::BlockScopeInfo>(FunctionScopes[e])) continue; @@ -1217,13 +1179,13 @@ public: } return nullptr; } - + template <typename ExprT> void recordUseOfEvaluatedWeak(const ExprT *E, bool IsRead=true) { if (!isUnevaluatedContext()) getCurFunction()->recordUseOfWeak(E, IsRead); } - + void PushCompoundScope(); void PopCompoundScope(); @@ -1234,10 +1196,8 @@ public: /// \brief Retrieve the current block, if any. sema::BlockScopeInfo *getCurBlock(); - /// Retrieve the current lambda scope info, if any. - /// \param IgnoreCapturedRegions true if should find the top-most lambda scope - /// info ignoring all inner captured regions scope infos. - sema::LambdaScopeInfo *getCurLambda(bool IgnoreCapturedRegions = false); + /// \brief Retrieve the current lambda scope info, if any. + sema::LambdaScopeInfo *getCurLambda(); /// \brief Retrieve the current generic lambda info, if any. sema::LambdaScopeInfo *getCurGenericLambda(); @@ -1309,9 +1269,7 @@ public: SourceLocation Loc, DeclarationName Entity); QualType BuildParenType(QualType T); QualType BuildAtomicType(QualType T, SourceLocation Loc); - QualType BuildReadPipeType(QualType T, - SourceLocation Loc); - QualType BuildWritePipeType(QualType T, + QualType BuildPipeType(QualType T, SourceLocation Loc); TypeSourceInfo *GetTypeForDeclarator(Declarator &D, Scope *S); @@ -1339,20 +1297,18 @@ public: bool CheckEquivalentExceptionSpec( const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID, const FunctionProtoType *Old, SourceLocation OldLoc, - const FunctionProtoType *New, SourceLocation NewLoc); - bool CheckExceptionSpecSubset(const PartialDiagnostic &DiagID, - const PartialDiagnostic &NestedDiagID, - const PartialDiagnostic &NoteID, - const FunctionProtoType *Superset, - SourceLocation SuperLoc, - const FunctionProtoType *Subset, - SourceLocation SubLoc); - bool CheckParamExceptionSpec(const PartialDiagnostic &NestedDiagID, - const PartialDiagnostic &NoteID, - const FunctionProtoType *Target, - SourceLocation TargetLoc, - const FunctionProtoType *Source, - SourceLocation SourceLoc); + const FunctionProtoType *New, SourceLocation NewLoc, + bool *MissingExceptionSpecification = nullptr, + bool *MissingEmptyExceptionSpecification = nullptr, + bool AllowNoexceptAllMatchWithNoSpec = false, + bool IsOperatorNew = false); + bool CheckExceptionSpecSubset( + const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID, + const FunctionProtoType *Superset, SourceLocation SuperLoc, + const FunctionProtoType *Subset, SourceLocation SubLoc); + bool CheckParamExceptionSpec(const PartialDiagnostic & NoteID, + const FunctionProtoType *Target, SourceLocation TargetLoc, + const FunctionProtoType *Source, SourceLocation SourceLoc); TypeResult ActOnTypeName(Scope *S, Declarator &D); @@ -1413,14 +1369,8 @@ private: bool RequireCompleteTypeImpl(SourceLocation Loc, QualType T, TypeDiagnoser *Diagnoser); - struct ModuleScope { - clang::Module *Module; - VisibleModuleSet OuterVisibleModules; - }; - /// The modules we're currently parsing. - llvm::SmallVector<ModuleScope, 16> ModuleScopes; - VisibleModuleSet VisibleModules; + llvm::SmallVector<VisibleModuleSet, 16> VisibleModulesStack; Module *CachedFakeTopLevelModule; @@ -1438,16 +1388,6 @@ public: bool isVisible(const NamedDecl *D) { return !D->isHidden() || isVisibleSlow(D); } - - /// Determine whether any declaration of an entity is visible. - bool - hasVisibleDeclaration(const NamedDecl *D, - llvm::SmallVectorImpl<Module *> *Modules = nullptr) { - return isVisible(D) || hasVisibleDeclarationSlow(D, Modules); - } - bool hasVisibleDeclarationSlow(const NamedDecl *D, - llvm::SmallVectorImpl<Module *> *Modules); - bool hasVisibleMergedDefinition(NamedDecl *Def); /// Determine if \p D has a visible definition. If not, suggest a declaration @@ -1464,11 +1404,6 @@ public: hasVisibleDefaultArgument(const NamedDecl *D, llvm::SmallVectorImpl<Module *> *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( - const NamedDecl *D, llvm::SmallVectorImpl<Module *> *Modules = nullptr); - /// Determine if \p A and \p B are equivalent internal linkage declarations /// from different modules, and thus an ambiguity error can be downgraded to /// an extension warning. @@ -1536,6 +1471,12 @@ public: NamedDecl *Previous; }; + /// List of decls defined in a function prototype. This contains EnumConstants + /// that incorrectly end up in translation unit scope because there is no + /// function to pin them on. ActOnFunctionDeclarator reads this list and patches + /// them into the FunctionDecl. + std::vector<NamedDecl*> DeclsInPrototypeScope; + DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType = nullptr); void DiagnoseUseOfUnimplementedSelectors(); @@ -1544,8 +1485,9 @@ public: ParsedType getTypeName(const IdentifierInfo &II, SourceLocation NameLoc, Scope *S, CXXScopeSpec *SS = nullptr, - bool isClassName = false, bool HasTrailingDot = false, - ParsedType ObjectType = nullptr, + bool isClassName = false, + bool HasTrailingDot = false, + ParsedType ObjectType = ParsedType(), bool IsCtorOrDtorName = false, bool WantNontrivialTypeSourceInfo = false, IdentifierInfo **CorrectedII = nullptr); @@ -1558,13 +1500,12 @@ public: ParsedType &SuggestedType, bool AllowClassTemplates = false); - /// Attempt to behave like MSVC in situations where lookup of an unqualified - /// type name has failed in a dependent context. In these situations, we - /// automatically form a DependentTypeName that will retry lookup in a related - /// scope during instantiation. - ParsedType ActOnMSVCUnknownTypeName(const IdentifierInfo &II, - SourceLocation NameLoc, - bool IsTemplateTypeArg); + /// \brief For compatibility with MSVC, we delay parsing of some default + /// template type arguments until instantiation time. Emits a warning and + /// returns a synthesized DependentNameType that isn't really dependent on any + /// other template arguments. + ParsedType ActOnDelayedDefaultTemplateArg(const IdentifierInfo &II, + SourceLocation NameLoc); /// \brief Describes the result of the name lookup and resolution performed /// by \c ClassifyName(). @@ -1704,27 +1645,12 @@ public: SourceLocation ConstQualLoc = SourceLocation(), SourceLocation VolatileQualLoc = SourceLocation(), SourceLocation RestrictQualLoc = SourceLocation(), - SourceLocation AtomicQualLoc = SourceLocation(), - SourceLocation UnalignedQualLoc = SourceLocation()); + SourceLocation AtomicQualLoc = SourceLocation()); static bool adjustContextForLocalExternDecl(DeclContext *&DC); void DiagnoseFunctionSpecifiers(const DeclSpec &DS); - NamedDecl *getShadowedDeclaration(const VarDecl *D, const LookupResult &R); - void CheckShadow(VarDecl *D, NamedDecl *ShadowedDecl, const LookupResult &R); + void CheckShadow(Scope *S, VarDecl *D, const LookupResult& R); void CheckShadow(Scope *S, VarDecl *D); - - /// Warn if 'E', which is an expression that is about to be modified, refers - /// to a shadowing declaration. - void CheckShadowingDeclModification(Expr *E, SourceLocation Loc); - - void DiagnoseShadowingLambdaDecls(const sema::LambdaScopeInfo *LSI); - -private: - /// Map of current shadowing declarations to shadowed declarations. Warn if - /// it looks like the user is trying to modify the shadowing declaration. - llvm::DenseMap<const NamedDecl *, const NamedDecl *> ShadowingDecls; - -public: void CheckCastAlign(Expr *Op, QualType T, SourceRange TRange); void handleTagNumbering(const TagDecl *Tag, Scope *TagScope); void setTagNameForLinkagePurposes(TagDecl *TagFromDeclSpec, @@ -1739,16 +1665,11 @@ public: TypeSourceInfo *TInfo, LookupResult &Previous, MultiTemplateParamsArg TemplateParamLists, - bool &AddToScope, - ArrayRef<BindingDecl *> Bindings = None); - NamedDecl * - ActOnDecompositionDeclarator(Scope *S, Declarator &D, - MultiTemplateParamsArg TemplateParamLists); + bool &AddToScope); // Returns true if the variable declaration is a redeclaration bool CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous); void CheckVariableDeclarationType(VarDecl *NewVD); - void CheckCompleteVariableDeclaration(VarDecl *VD); - void CheckCompleteDecompositionDeclaration(DecompositionDecl *DD); + void CheckCompleteVariableDeclaration(VarDecl *var); void MaybeSuggestAddingStaticToDecl(const FunctionDecl *D); NamedDecl* ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, @@ -1770,7 +1691,6 @@ public: bool CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, LookupResult &Previous, bool IsExplicitSpecialization); - bool shouldLinkDependentDeclWithPrevious(Decl *D, Decl *OldDecl); void CheckMain(FunctionDecl *FD, const DeclSpec &D); void CheckMSVCRTEntryPoint(FunctionDecl *FD); Decl *ActOnParamDeclarator(Scope *S, Declarator &D); @@ -1791,11 +1711,10 @@ public: bool SetParamDefaultArgument(ParmVarDecl *Param, Expr *DefaultArg, SourceLocation EqualLoc); - void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit); - void ActOnUninitializedDecl(Decl *dcl); + void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit, + bool TypeMayContainAuto); + void ActOnUninitializedDecl(Decl *dcl, bool TypeMayContainAuto); void ActOnInitializerError(Decl *Dcl); - bool canInitializeWithParenthesizedList(QualType TargetType); - void ActOnPureSpecifier(Decl *D, SourceLocation PureSpecLoc); void ActOnCXXForRangeDecl(Decl *D); StmtResult ActOnCXXForRangeIdentifier(Scope *S, SourceLocation IdentLoc, @@ -1807,7 +1726,8 @@ public: void FinalizeDeclaration(Decl *D); DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS, ArrayRef<Decl *> Group); - DeclGroupPtrTy BuildDeclaratorGroup(MutableArrayRef<Decl *> Group); + DeclGroupPtrTy BuildDeclaratorGroup(MutableArrayRef<Decl *> Group, + bool TypeMayContainAuto = true); /// Should be called on all declarations that might have attached /// documentation comments. @@ -1852,7 +1772,7 @@ public: Decl *ActOnFinishFunctionBody(Decl *Decl, Stmt *Body); Decl *ActOnFinishFunctionBody(Decl *Decl, Stmt *Body, bool IsInstantiation); Decl *ActOnSkippedFunctionBody(Decl *Decl); - void ActOnFinishInlineFunctionDef(FunctionDecl *D); + void ActOnFinishInlineMethodDef(CXXMethodDecl *D); /// ActOnFinishDelayedAttribute - Invoked when we have finished parsing an /// attribute for which parsing is delayed. @@ -1860,14 +1780,16 @@ public: /// \brief Diagnose any unused parameters in the given sequence of /// ParmVarDecl pointers. - void DiagnoseUnusedParameters(ArrayRef<ParmVarDecl *> Parameters); + void DiagnoseUnusedParameters(ParmVarDecl * const *Begin, + ParmVarDecl * const *End); /// \brief Diagnose whether the size of parameters or return value of a /// function or obj-c method definition is pass-by-value and larger than a /// specified threshold. - void - DiagnoseSizeOfParametersAndReturnValue(ArrayRef<ParmVarDecl *> Parameters, - QualType ReturnTy, NamedDecl *D); + void DiagnoseSizeOfParametersAndReturnValue(ParmVarDecl * const *Begin, + ParmVarDecl * const *End, + QualType ReturnTy, + NamedDecl *D); void DiagnoseInvalidJumps(Stmt *Body); Decl *ActOnFileScopeAsmDecl(Expr *expr, @@ -1879,17 +1801,6 @@ public: AttributeList *AttrList, SourceLocation SemiLoc); - enum class ModuleDeclKind { - Module, ///< 'module X;' - Partition, ///< 'module partition X;' - Implementation, ///< 'module implementation X;' - }; - - /// The parser has processed a module-declaration that begins the definition - /// of a module interface or implementation. - DeclGroupPtrTy ActOnModuleDecl(SourceLocation ModuleLoc, ModuleDeclKind MDK, - ModuleIdPath Path); - /// \brief The parser has processed a module import declaration. /// /// \param AtLoc The location of the '@' symbol, if any. @@ -1903,13 +1814,16 @@ public: /// \brief The parser has processed a module import translated from a /// #include or similar preprocessing directive. void ActOnModuleInclude(SourceLocation DirectiveLoc, Module *Mod); - void BuildModuleInclude(SourceLocation DirectiveLoc, Module *Mod); /// \brief The parsed has entered a submodule. void ActOnModuleBegin(SourceLocation DirectiveLoc, Module *Mod); /// \brief The parser has left a submodule. void ActOnModuleEnd(SourceLocation DirectiveLoc, Module *Mod); + /// \brief Check if module import may be found in the current context, + /// emit error if not. + void diagnoseMisplacedModuleImport(Module *M, SourceLocation ImportLoc); + /// \brief Create an implicit import of the given module at the given /// source location, for error recovery, if possible. /// @@ -1924,35 +1838,17 @@ public: enum class MissingImportKind { Declaration, Definition, - DefaultArgument, - ExplicitSpecialization, - PartialSpecialization + DefaultArgument }; /// \brief Diagnose that the specified declaration needs to be visible but /// isn't, and suggest a module import that would resolve the problem. void diagnoseMissingImport(SourceLocation Loc, NamedDecl *Decl, - MissingImportKind MIK, bool Recover = true); + bool NeedDefinition, bool Recover = true); void diagnoseMissingImport(SourceLocation Loc, NamedDecl *Decl, SourceLocation DeclLoc, ArrayRef<Module *> Modules, MissingImportKind MIK, bool Recover); - Decl *ActOnStartExportDecl(Scope *S, SourceLocation ExportLoc, - SourceLocation LBraceLoc); - Decl *ActOnFinishExportDecl(Scope *S, Decl *ExportDecl, - SourceLocation RBraceLoc); - - /// \brief We've found a use of a templated declaration that would trigger an - /// implicit instantiation. Check that any relevant explicit specializations - /// and partial specializations are visible, and diagnose if not. - void checkSpecializationVisibility(SourceLocation Loc, NamedDecl *Spec); - - /// \brief We've found a use of a template specialization that would select a - /// partial specialization. Check that the partial specialization is visible, - /// and diagnose if not. - void checkPartialSpecializationVisibility(SourceLocation Loc, - NamedDecl *Spec); - /// \brief Retrieve a suitable printing policy. PrintingPolicy getPrintingPolicy() const { return getPrintingPolicy(Context, PP); @@ -1966,12 +1862,12 @@ public: void ActOnPopScope(SourceLocation Loc, Scope *S); void ActOnTranslationUnitScope(Scope *S); - Decl *ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS, - RecordDecl *&AnonRecord); - Decl *ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS, + Decl *ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, + DeclSpec &DS); + Decl *ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, + DeclSpec &DS, MultiTemplateParamsArg TemplateParams, - bool IsExplicitInstantiation, - RecordDecl *&AnonRecord); + bool IsExplicitInstantiation = false); Decl *BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, AccessSpecifier AS, @@ -1981,24 +1877,6 @@ public: Decl *BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS, RecordDecl *Record); - /// Common ways to introduce type names without a tag for use in diagnostics. - /// Keep in sync with err_tag_reference_non_tag. - enum NonTagKind { - NTK_NonStruct, - NTK_NonClass, - NTK_NonUnion, - NTK_NonEnum, - NTK_Typedef, - NTK_TypeAlias, - NTK_Template, - NTK_TypeAliasTemplate, - NTK_TemplateTemplateArgument, - }; - - /// Given a non-tag type declaration, returns an enum useful for indicating - /// what kind of non-tag type this is. - NonTagKind getNonTagTypeDeclKind(const Decl *D, TagTypeKind TTK); - bool isAcceptableTagRedeclaration(const TagDecl *Previous, TagTypeKind NewTag, bool isDefinition, SourceLocation NewTagLoc, @@ -2103,7 +1981,7 @@ public: /// ActOnTagFinishDefinition - Invoked once we have finished parsing /// the definition of a tag (enumeration, class, struct, or union). void ActOnTagFinishDefinition(Scope *S, Decl *TagDecl, - SourceRange BraceRange); + SourceLocation RBraceLoc); void ActOnTagFinishSkippedDefinition(SkippedDefinitionContext Context); @@ -2140,8 +2018,8 @@ public: SourceLocation IdLoc, IdentifierInfo *Id, AttributeList *Attrs, SourceLocation EqualLoc, Expr *Val); - void ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange, - Decl *EnumDecl, + void ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, + SourceLocation RBraceLoc, Decl *EnumDecl, ArrayRef<Decl *> Elements, Scope *S, AttributeList *Attr); @@ -2226,13 +2104,11 @@ public: /// Attribute merging methods. Return true if a new attribute was added. AvailabilityAttr *mergeAvailabilityAttr(NamedDecl *D, SourceRange Range, IdentifierInfo *Platform, - bool Implicit, VersionTuple Introduced, VersionTuple Deprecated, VersionTuple Obsoleted, bool IsUnavailable, StringRef Message, - bool IsStrict, StringRef Replacement, AvailabilityMergeKind AMK, unsigned AttrSpellingListIndex); TypeVisibilityAttr *mergeTypeVisibilityAttr(Decl *D, SourceRange Range, @@ -2241,8 +2117,6 @@ public: VisibilityAttr *mergeVisibilityAttr(Decl *D, SourceRange Range, VisibilityAttr::VisibilityType Vis, unsigned AttrSpellingListIndex); - UuidAttr *mergeUuidAttr(Decl *D, SourceRange Range, - unsigned AttrSpellingListIndex, StringRef Uuid); DLLImportAttr *mergeDLLImportAttr(Decl *D, SourceRange Range, unsigned AttrSpellingListIndex); DLLExportAttr *mergeDLLExportAttr(Decl *D, SourceRange Range, @@ -2281,7 +2155,6 @@ public: void MergeVarDecl(VarDecl *New, LookupResult &Previous); void MergeVarDeclTypes(VarDecl *New, VarDecl *Old, bool MergeTypeWithOld); void MergeVarDeclExceptionSpecs(VarDecl *New, VarDecl *Old); - bool checkVarDeclRedefinition(VarDecl *OldDefn, VarDecl *NewDefn); bool MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, Scope *S); // AssignmentAction - This is used by all the assignment diagnostic functions @@ -2316,8 +2189,7 @@ public: const LookupResult &OldDecls, NamedDecl *&OldDecl, bool IsForUsingDecl); - bool IsOverload(FunctionDecl *New, FunctionDecl *Old, bool IsForUsingDecl, - bool ConsiderCudaAttrs = true); + bool IsOverload(FunctionDecl *New, FunctionDecl *Old, bool IsForUsingDecl); /// \brief Checks availability of the function depending on the current /// function context.Inside an unavailable function,unavailability is ignored. @@ -2368,7 +2240,7 @@ public: bool IgnoreBaseAccess); bool IsQualificationConversion(QualType FromType, QualType ToType, bool CStyle, bool &ObjCLifetimeConversion); - bool IsFunctionConversion(QualType FromType, QualType ToType, + bool IsNoReturnConversion(QualType FromType, QualType ToType, QualType &ResultTy); bool DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType); bool isSameOrCompatibleFunctionType(CanQualType Param, CanQualType Arg); @@ -2399,8 +2271,7 @@ public: CCEK_CaseValue, ///< Expression in a case label. CCEK_Enumerator, ///< Enumerator value with fixed underlying type. CCEK_TemplateArg, ///< Value of a non-type template parameter. - CCEK_NewExpr, ///< Constant expression in a noptr-new-declarator. - CCEK_ConstexprIf ///< Condition in a constexpr if statement. + CCEK_NewExpr ///< Constant expression in a noptr-new-declarator. }; ExprResult CheckConvertedConstantExpression(Expr *From, QualType T, llvm::APSInt &Value, CCEKind CCE); @@ -2512,17 +2383,16 @@ public: // Members have to be NamespaceDecl* or TranslationUnitDecl*. // TODO: make this is a typesafe union. - typedef llvm::SmallSetVector<DeclContext *, 16> AssociatedNamespaceSet; - typedef llvm::SmallSetVector<CXXRecordDecl *, 16> AssociatedClassSet; + typedef llvm::SmallPtrSet<DeclContext *, 16> AssociatedNamespaceSet; + typedef llvm::SmallPtrSet<CXXRecordDecl *, 16> AssociatedClassSet; void AddOverloadCandidate(FunctionDecl *Function, DeclAccessPair FoundDecl, ArrayRef<Expr *> Args, - OverloadCandidateSet &CandidateSet, + OverloadCandidateSet& CandidateSet, bool SuppressUserConversions = false, bool PartialOverloading = false, - bool AllowExplicit = false, - ConversionSequenceList EarlyConversions = None); + bool AllowExplicit = false); void AddFunctionCandidates(const UnresolvedSetImpl &Functions, ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet, @@ -2542,8 +2412,7 @@ public: ArrayRef<Expr *> Args, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions = false, - bool PartialOverloading = false, - ConversionSequenceList EarlyConversions = None); + bool PartialOverloading = false); void AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, @@ -2561,16 +2430,6 @@ public: OverloadCandidateSet& CandidateSet, bool SuppressUserConversions = false, bool PartialOverloading = false); - bool CheckNonDependentConversions(FunctionTemplateDecl *FunctionTemplate, - ArrayRef<QualType> ParamTypes, - ArrayRef<Expr *> Args, - OverloadCandidateSet &CandidateSet, - ConversionSequenceList &Conversions, - bool SuppressUserConversions, - CXXRecordDecl *ActingContext = nullptr, - QualType ObjectType = QualType(), - Expr::Classification - ObjectClassification = {}); void AddConversionCandidate(CXXConversionDecl *Conversion, DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, @@ -2594,7 +2453,7 @@ public: OverloadCandidateSet& CandidateSet, SourceRange OpRange = SourceRange()); void AddBuiltinCandidate(QualType ResultTy, QualType *ParamTys, - ArrayRef<Expr *> Args, + ArrayRef<Expr *> Args, OverloadCandidateSet& CandidateSet, bool IsAssignmentOperator = false, unsigned NumContextualBoolArguments = 0); @@ -2609,8 +2468,7 @@ public: bool PartialOverloading = false); // Emit as a 'note' the specific overload candidate - void NoteOverloadCandidate(NamedDecl *Found, FunctionDecl *Fn, - QualType DestType = QualType(), + void NoteOverloadCandidate(FunctionDecl *Fn, QualType DestType = QualType(), bool TakingAddress = false); // Emit as a series of 'note's all template and non-templates identified by @@ -2623,28 +2481,6 @@ public: EnableIfAttr *CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args, bool MissingImplicitThis = false); - /// Emit diagnostics for the diagnose_if attributes on Function, ignoring any - /// non-ArgDependent DiagnoseIfAttrs. - /// - /// Argument-dependent diagnose_if attributes should be checked each time a - /// function is used as a direct callee of a function call. - /// - /// Returns true if any errors were emitted. - bool diagnoseArgDependentDiagnoseIfAttrs(const FunctionDecl *Function, - const Expr *ThisArg, - ArrayRef<const Expr *> Args, - SourceLocation Loc); - - /// Emit diagnostics for the diagnose_if attributes on Function, ignoring any - /// ArgDependent DiagnoseIfAttrs. - /// - /// Argument-independent diagnose_if attributes should be checked on every use - /// of a function. - /// - /// Returns true if any errors were emitted. - bool diagnoseArgIndependentDiagnoseIfAttrs(const FunctionDecl *Function, - SourceLocation Loc); - /// Returns whether the given function's address can be taken or not, /// optionally emitting a diagnostic if the address can't be taken. /// @@ -2669,12 +2505,6 @@ public: bool *pHadMultipleCandidates = nullptr); FunctionDecl * - resolveAddressOfOnlyViableOverloadCandidate(Expr *E, - DeclAccessPair &FoundResult); - - bool resolveAndFixAddressOfOnlyViableOverloadCandidate(ExprResult &SrcExpr); - - FunctionDecl * ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl, bool Complain = false, DeclAccessPair *Found = nullptr); @@ -2764,7 +2594,8 @@ public: CallExpr *CE, FunctionDecl *FD); /// Helpers for dealing with blocks and functions. - bool CheckParmsForFunctionDef(ArrayRef<ParmVarDecl *> Parameters, + bool CheckParmsForFunctionDef(ParmVarDecl *const *Param, + ParmVarDecl *const *ParamEnd, bool CheckParameterNames); void CheckCXXDefaultArguments(FunctionDecl *FD); void CheckExtraCXXDefaultArguments(Declarator &D); @@ -2839,8 +2670,6 @@ public: LookupObjCProtocolName, /// Look up implicit 'self' parameter of an objective-c method. LookupObjCImplicitSelfParam, - /// \brief Look up the name of an OpenMP user-defined reduction operation. - LookupOMPReductionName, /// \brief Look up any declaration with any name. LookupAnyName }; @@ -2896,8 +2725,8 @@ private: TypoDiagnosticGenerator DiagHandler; TypoRecoveryCallback RecoveryHandler; TypoExprState(); - TypoExprState(TypoExprState &&other) noexcept; - TypoExprState &operator=(TypoExprState &&other) noexcept; + TypoExprState(TypoExprState&& other) LLVM_NOEXCEPT; + TypoExprState& operator=(TypoExprState&& other) LLVM_NOEXCEPT; }; /// \brief The set of unhandled TypoExprs and their associated state. @@ -3112,7 +2941,7 @@ public: bool isValidPointerAttrType(QualType T, bool RefOkay = false); bool CheckRegparmAttr(const AttributeList &attr, unsigned &value); - bool CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC, + bool CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC, const FunctionDecl *FD = nullptr); bool CheckNoReturnAttr(const AttributeList &attr); bool checkStringLiteralArgumentAttr(const AttributeList &Attr, @@ -3156,14 +2985,10 @@ public: /// method) or an Objective-C property attribute, rather than as an /// underscored type specifier. /// - /// \param allowArrayTypes Whether to accept nullability specifiers on an - /// array type (e.g., because it will decay to a pointer). - /// /// \returns true if nullability cannot be applied, false otherwise. bool checkNullabilityTypeSpecifier(QualType &type, NullabilityKind nullability, SourceLocation nullabilityLoc, - bool isContextSensitive, - bool allowArrayTypes); + bool isContextSensitive); /// \brief Stmt attributes - this routine is the top level dispatcher. StmtResult ProcessStmtAttributes(Stmt *Stmt, AttributeList *Attrs, @@ -3218,18 +3043,18 @@ public: /// declared in class 'IFace'. bool IvarBacksCurrentMethodAccessor(ObjCInterfaceDecl *IFace, ObjCMethodDecl *Method, ObjCIvarDecl *IV); - + /// DiagnoseUnusedBackingIvarInAccessor - Issue an 'unused' warning if ivar which /// backs the property is not used in the property's accessor. void DiagnoseUnusedBackingIvarInAccessor(Scope *S, const ObjCImplementationDecl *ImplD); - + /// GetIvarBackingPropertyAccessor - If method is a property setter/getter and /// it property has a backing ivar, returns this ivar; otherwise, returns NULL. /// It also returns ivar's property on success. ObjCIvarDecl *GetIvarBackingPropertyAccessor(const ObjCMethodDecl *Method, const ObjCPropertyDecl *&PDecl) const; - + /// Called by ActOnProperty to handle \@property declarations in /// class extensions. ObjCPropertyDecl *HandlePropertyInClassExtension(Scope *S, @@ -3320,33 +3145,26 @@ private: public: /// \brief - Returns instance or factory methods in global method pool for - /// given selector. It checks the desired kind first, if none is found, and - /// parameter checkTheOther is set, it then checks the other kind. If no such - /// method or only one method is found, function returns false; otherwise, it - /// returns true. - bool - CollectMultipleMethodsInGlobalPool(Selector Sel, - SmallVectorImpl<ObjCMethodDecl*>& Methods, - bool InstanceFirst, bool CheckTheOther, - const ObjCObjectType *TypeBound = nullptr); - - bool - AreMultipleMethodsInGlobalPool(Selector Sel, ObjCMethodDecl *BestMethod, - SourceRange R, bool receiverIdOrClass, - SmallVectorImpl<ObjCMethodDecl*>& Methods); - - void - DiagnoseMultipleMethodInGlobalPool(SmallVectorImpl<ObjCMethodDecl*> &Methods, - Selector Sel, SourceRange R, - bool receiverIdOrClass); + /// given selector. If no such method or only one method found, function returns + /// false; otherwise, it returns true + bool CollectMultipleMethodsInGlobalPool(Selector Sel, + SmallVectorImpl<ObjCMethodDecl*>& Methods, + bool instance); + + bool AreMultipleMethodsInGlobalPool(Selector Sel, ObjCMethodDecl *BestMethod, + SourceRange R, + bool receiverIdOrClass); + + void DiagnoseMultipleMethodInGlobalPool(SmallVectorImpl<ObjCMethodDecl*> &Methods, + Selector Sel, SourceRange R, + bool receiverIdOrClass); private: /// \brief - Returns a selector which best matches given argument list or /// nullptr if none could be found ObjCMethodDecl *SelectBestMethod(Selector Sel, MultiExprArg Args, - bool IsInstance, - SmallVectorImpl<ObjCMethodDecl*>& Methods); - + bool IsInstance); + /// \brief Record the typo correction failure and return an empty correction. TypoCorrection FailedCorrection(IdentifierInfo *Typo, SourceLocation TypoLoc, @@ -3406,7 +3224,6 @@ public: public: class FullExprArg { public: - FullExprArg() : E(nullptr) { } FullExprArg(Sema &actions) : E(nullptr) { } ExprResult release() { @@ -3500,30 +3317,27 @@ public: ArrayRef<const Attr*> Attrs, Stmt *SubStmt); - class ConditionResult; - StmtResult ActOnIfStmt(SourceLocation IfLoc, bool IsConstexpr, - Stmt *InitStmt, - ConditionResult Cond, Stmt *ThenVal, - SourceLocation ElseLoc, Stmt *ElseVal); - StmtResult BuildIfStmt(SourceLocation IfLoc, bool IsConstexpr, - Stmt *InitStmt, - ConditionResult Cond, Stmt *ThenVal, + StmtResult ActOnIfStmt(SourceLocation IfLoc, + FullExprArg CondVal, Decl *CondVar, + Stmt *ThenVal, SourceLocation ElseLoc, Stmt *ElseVal); StmtResult ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, - Stmt *InitStmt, - ConditionResult Cond); + Expr *Cond, + Decl *CondVar); StmtResult ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, Stmt *Body); - StmtResult ActOnWhileStmt(SourceLocation WhileLoc, ConditionResult Cond, - Stmt *Body); + StmtResult ActOnWhileStmt(SourceLocation WhileLoc, + FullExprArg Cond, + Decl *CondVar, Stmt *Body); StmtResult ActOnDoStmt(SourceLocation DoLoc, Stmt *Body, - SourceLocation WhileLoc, SourceLocation CondLParen, - Expr *Cond, SourceLocation CondRParen); + SourceLocation WhileLoc, + SourceLocation CondLParen, Expr *Cond, + SourceLocation CondRParen); StmtResult ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc, - Stmt *First, - ConditionResult Second, + Stmt *First, FullExprArg Second, + Decl *SecondVar, FullExprArg Third, SourceLocation RParenLoc, Stmt *Body); @@ -3554,7 +3368,7 @@ public: StmtResult BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation CoawaitLoc, SourceLocation ColonLoc, - Stmt *RangeDecl, Stmt *Begin, Stmt *End, + Stmt *RangeDecl, Stmt *BeginEndDecl, Expr *Cond, Expr *Inc, Stmt *LoopVarDecl, SourceLocation RParenLoc, @@ -3582,9 +3396,9 @@ public: SourceLocation Loc, unsigned NumParams); VarDecl *getCopyElisionCandidate(QualType ReturnType, Expr *E, - bool AllowParamOrMoveConstructible); + bool AllowFunctionParameters); bool isCopyElisionCandidate(QualType ReturnType, const VarDecl *VD, - bool AllowParamOrMoveConstructible); + bool AllowFunctionParameters); StmtResult ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp, Scope *CurScope); @@ -3722,27 +3536,26 @@ public: void redelayDiagnostics(sema::DelayedDiagnosticPool &pool); - void EmitAvailabilityWarning(AvailabilityResult AR, NamedDecl *D, - StringRef Message, SourceLocation Loc, + enum AvailabilityDiagnostic { AD_Deprecation, AD_Unavailable, AD_Partial }; + + void EmitAvailabilityWarning(AvailabilityDiagnostic AD, + NamedDecl *D, StringRef Message, + SourceLocation Loc, const ObjCInterfaceDecl *UnknownObjCClass, - const ObjCPropertyDecl *ObjCProperty, + const ObjCPropertyDecl *ObjCProperty, bool ObjCPropertyAccess); bool makeUnavailableInSystemHeader(SourceLocation loc, UnavailableAttr::ImplicitReason reason); - /// \brief Issue any -Wunguarded-availability warnings in \c FD - void DiagnoseUnguardedAvailabilityViolations(Decl *FD); - //===--------------------------------------------------------------------===// // Expression Parsing Callbacks: SemaExpr.cpp. - bool CanUseDecl(NamedDecl *D, bool TreatUnavailableAsInvalid); + bool CanUseDecl(NamedDecl *D); bool DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc, const ObjCInterfaceDecl *UnknownObjCClass=nullptr, bool ObjCPropertyAccess=false); void NoteDeletedFunction(FunctionDecl *FD); - void NoteDeletedInheritingConstructor(CXXConstructorDecl *CD); std::string getDeletedOrUnavailableSuffix(const FunctionDecl *FD); bool DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *PD, ObjCMethodDecl *Getter, @@ -3772,15 +3585,9 @@ public: // for expressions referring to a decl; these exist because odr-use marking // needs to be delayed for some constant variables when we build one of the // named expressions. - // - // MightBeOdrUse indicates whether the use could possibly be an odr-use, and - // should usually be true. This only needs to be set to false if the lack of - // odr-use cannot be determined from the current context (for instance, - // because the name denotes a virtual function and was written without an - // explicit nested-name-specifier). - void MarkAnyDeclReferenced(SourceLocation Loc, Decl *D, bool MightBeOdrUse); + void MarkAnyDeclReferenced(SourceLocation Loc, Decl *D, bool OdrUse); void MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func, - bool MightBeOdrUse = true); + bool OdrUse = true); void MarkVariableReferenced(SourceLocation Loc, VarDecl *Var); void MarkDeclRefReferenced(DeclRefExpr *E); void MarkMemberReferenced(MemberExpr *E); @@ -3819,16 +3626,16 @@ public: /// /// \param FunctionScopeIndexToStopAt If non-null, it points to the index /// of the FunctionScopeInfo stack beyond which we do not attempt to capture. - /// This is useful when enclosing lambdas must speculatively capture + /// This is useful when enclosing lambdas must speculatively capture /// variables that may or may not be used in certain specializations of /// a nested generic lambda. - /// + /// /// \returns true if an error occurred (i.e., the variable cannot be /// captured) and false if the capture succeeded. bool tryCaptureVariable(VarDecl *Var, SourceLocation Loc, TryCaptureKind Kind, SourceLocation EllipsisLoc, bool BuildAndDiagnose, QualType &CaptureType, - QualType &DeclRefType, + QualType &DeclRefType, const unsigned *const FunctionScopeIndexToStopAt); /// \brief Try to capture the given variable. @@ -3843,9 +3650,6 @@ public: /// variable will have in the given scope. QualType getCapturedDeclRefType(VarDecl *Var, SourceLocation Loc); - /// Mark all of the declarations referenced within a particular AST node as - /// referenced. Used when template instantiation instantiates a non-dependent - /// type -- entities referenced by the type are now referenced. void MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T); void MarkDeclarationsReferencedInExpr(Expr *E, bool SkipLocalVariables = false); @@ -4069,12 +3873,6 @@ public: bool SuppressQualifierCheck = false, ActOnMemberAccessExtraArgs *ExtraArgs = nullptr); - ExprResult BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow, - SourceLocation OpLoc, - const CXXScopeSpec &SS, FieldDecl *Field, - DeclAccessPair FoundDecl, - const DeclarationNameInfo &MemberNameInfo); - ExprResult PerformMemberExprBaseConversion(Expr *Base, bool IsArrow); bool CheckQualifiedMemberReference(Expr *BaseExpr, QualType BaseType, @@ -4172,8 +3970,6 @@ public: ExprResult CreateBuiltinBinOp(SourceLocation OpLoc, BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr); - void DiagnoseCommaOperator(const Expr *LHS, SourceLocation Loc); - /// ActOnConditionalOp - Parse a ?: operation. Note that 'LHS' may be null /// in the case of a the GNU conditional expr extension. ExprResult ActOnConditionalOp(SourceLocation QuestionLoc, @@ -4311,10 +4107,7 @@ public: NamespaceDecl *getStdNamespace() const; NamespaceDecl *getOrCreateStdNamespace(); - NamespaceDecl *lookupStdExperimentalNamespace(); - CXXRecordDecl *getStdBadAlloc() const; - EnumDecl *getStdAlignValT() const; /// \brief Tests whether Ty is an instance of std::initializer_list and, if /// it is and Element is not NULL, assigns the element type to Element. @@ -4362,40 +4155,30 @@ public: SourceLocation NameLoc, const LookupResult &Previous); bool CheckUsingDeclQualifier(SourceLocation UsingLoc, - bool HasTypename, const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, SourceLocation NameLoc); NamedDecl *BuildUsingDeclaration(Scope *S, AccessSpecifier AS, SourceLocation UsingLoc, - bool HasTypenameKeyword, - SourceLocation TypenameLoc, CXXScopeSpec &SS, DeclarationNameInfo NameInfo, - SourceLocation EllipsisLoc, AttributeList *AttrList, - bool IsInstantiation); - NamedDecl *BuildUsingPackDecl(NamedDecl *InstantiatedFrom, - ArrayRef<NamedDecl *> Expansions); + bool IsInstantiation, + bool HasTypenameKeyword, + SourceLocation TypenameLoc); bool CheckInheritingConstructorUsingDecl(UsingDecl *UD); - /// Given a derived-class using shadow declaration for a constructor and the - /// correspnding base class constructor, find or create the implicit - /// synthesized derived class constructor to use for this initialization. - CXXConstructorDecl * - findInheritingConstructor(SourceLocation Loc, CXXConstructorDecl *BaseCtor, - ConstructorUsingShadowDecl *DerivedShadow); - Decl *ActOnUsingDeclaration(Scope *CurScope, AccessSpecifier AS, + bool HasUsingKeyword, SourceLocation UsingLoc, - SourceLocation TypenameLoc, CXXScopeSpec &SS, UnqualifiedId &Name, - SourceLocation EllipsisLoc, - AttributeList *AttrList); + AttributeList *AttrList, + bool HasTypenameKeyword, + SourceLocation TypenameLoc); Decl *ActOnAliasDeclaration(Scope *CurScope, AccessSpecifier AS, MultiTemplateParamsArg TemplateParams, @@ -4411,29 +4194,16 @@ public: /// \param ConstructKind - a CXXConstructExpr::ConstructionKind ExprResult BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, - NamedDecl *FoundDecl, CXXConstructorDecl *Constructor, MultiExprArg Exprs, bool HadMultipleCandidates, bool IsListInitialization, bool IsStdInitListInitialization, bool RequiresZeroInit, unsigned ConstructKind, SourceRange ParenRange); - /// Build a CXXConstructExpr whose constructor has already been resolved if - /// it denotes an inherited constructor. - ExprResult - BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, - CXXConstructorDecl *Constructor, bool Elidable, - MultiExprArg Exprs, - bool HadMultipleCandidates, bool IsListInitialization, - bool IsStdInitListInitialization, - bool RequiresZeroInit, unsigned ConstructKind, - SourceRange ParenRange); - // FIXME: Can we remove this and have the above BuildCXXConstructExpr check if // the constructor can be elidable? ExprResult BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, - NamedDecl *FoundDecl, CXXConstructorDecl *Constructor, bool Elidable, MultiExprArg Exprs, bool HadMultipleCandidates, bool IsListInitialization, @@ -4442,12 +4212,6 @@ public: ExprResult BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field); - - /// Instantiate or parse a C++ default argument expression as necessary. - /// Return true on error. - bool CheckCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD, - ParmVarDecl *Param); - /// BuildCXXDefaultArgExpr - Creates a CXXDefaultArgExpr, instantiating /// the default expr if needed. ExprResult BuildCXXDefaultArgExpr(SourceLocation CallLoc, @@ -4559,8 +4323,7 @@ public: /// \brief Determine what sort of exception specification an inheriting /// constructor of a class will have. ImplicitExceptionSpecification - ComputeInheritingCtorExceptionSpec(SourceLocation Loc, - CXXConstructorDecl *CD); + ComputeInheritingCtorExceptionSpec(CXXConstructorDecl *CD); /// \brief Evaluate the implicit exception specification for a defaulted /// special member function. @@ -4590,12 +4353,9 @@ public: ArrayRef<SourceRange> DynamicExceptionRanges, Expr *NoexceptExpr); - class InheritedConstructorInfo; - /// \brief Determine if a special member function should have a deleted /// definition when it is defaulted. bool ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, - InheritedConstructorInfo *ICI = nullptr, bool Diagnose = false); /// \brief Declare the implicit default constructor for the given class. @@ -4632,6 +4392,12 @@ public: void AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl, CXXDestructorDecl *Destructor); + /// \brief Declare all inheriting constructors for the given class. + /// + /// \param ClassDecl The class declaration into which the inheriting + /// constructors will be added. + void DeclareInheritingConstructors(CXXRecordDecl *ClassDecl); + /// \brief Define the specified inheriting constructor. void DefineInheritingConstructor(SourceLocation UseLoc, CXXConstructorDecl *Constructor); @@ -4692,9 +4458,6 @@ public: /// class. void ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class); - /// \brief Check a completed declaration of an implicit special member. - void CheckImplicitSpecialMemberDeclaration(Scope *S, FunctionDecl *FD); - /// \brief Determine whether the given function is an implicitly-deleted /// special member function. bool isImplicitlyDeleted(FunctionDecl *FD); @@ -4843,15 +4606,14 @@ public: /// /// \param FunctionScopeIndexToStopAt If non-null, it points to the index /// of the FunctionScopeInfo stack beyond which we do not attempt to capture. - /// This is useful when enclosing lambdas must speculatively capture + /// This is useful when enclosing lambdas must speculatively capture /// 'this' that may or may not be used in certain specializations of - /// a nested generic lambda (depending on whether the name resolves to + /// a nested generic lambda (depending on whether the name resolves to /// a non-static member function or a static function). /// \return returns 'true' if failed, 'false' if success. - bool CheckCXXThisCapture(SourceLocation Loc, bool Explicit = false, + bool CheckCXXThisCapture(SourceLocation Loc, bool Explicit = false, bool BuildAndDiagnose = true, - const unsigned *const FunctionScopeIndexToStopAt = nullptr, - bool ByCopy = false); + const unsigned *const FunctionScopeIndexToStopAt = nullptr); /// \brief Determine whether the given type is the type of *this that is used /// outside of the body of a member function for a type that is currently @@ -4865,10 +4627,6 @@ public: /// ActOnObjCBoolLiteral - Parse {__objc_yes,__objc_no} literals. ExprResult ActOnObjCBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind); - ExprResult - ActOnObjCAvailabilityCheckExpr(llvm::ArrayRef<AvailabilitySpec> AvailSpecs, - SourceLocation AtLoc, SourceLocation RParen); - /// ActOnCXXNullPtrLiteral - Parse 'nullptr'. ExprResult ActOnCXXNullPtrLiteral(SourceLocation Loc); @@ -4908,37 +4666,43 @@ public: TypeSourceInfo *AllocTypeInfo, Expr *ArraySize, SourceRange DirectInitRange, - Expr *Initializer); + Expr *Initializer, + bool TypeMayContainAuto = true); bool CheckAllocatedType(QualType AllocType, SourceLocation Loc, SourceRange R); bool FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, bool UseGlobal, QualType AllocType, bool IsArray, - bool &PassAlignment, MultiExprArg PlaceArgs, + MultiExprArg PlaceArgs, FunctionDecl *&OperatorNew, FunctionDecl *&OperatorDelete); + bool FindAllocationOverload(SourceLocation StartLoc, SourceRange Range, + DeclarationName Name, MultiExprArg Args, + DeclContext *Ctx, + bool AllowMissing, FunctionDecl *&Operator, + bool Diagnose = true); void DeclareGlobalNewDelete(); void DeclareGlobalAllocationFunction(DeclarationName Name, QualType Return, - ArrayRef<QualType> Params); + QualType Param1, + QualType Param2 = QualType(), + bool addRestrictAttr = false); bool FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, DeclarationName Name, FunctionDecl* &Operator, bool Diagnose = true); FunctionDecl *FindUsualDeallocationFunction(SourceLocation StartLoc, bool CanProvideSize, - bool Overaligned, DeclarationName Name); - FunctionDecl *FindDeallocationFunctionForDestructor(SourceLocation StartLoc, - CXXRecordDecl *RD); /// ActOnCXXDelete - Parsed a C++ 'delete' expression ExprResult ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, bool ArrayForm, Expr *Operand); - void CheckVirtualDtorCall(CXXDestructorDecl *dtor, SourceLocation Loc, - bool IsDelete, bool CallCanBeVirtual, - bool WarnOnNonAbstractTypes, - SourceLocation DtorLoc); + + DeclResult ActOnCXXConditionDeclaration(Scope *S, Declarator &D); + ExprResult CheckConditionVariable(VarDecl *ConditionVar, + SourceLocation StmtLoc, + bool ConvertToBoolean); ExprResult ActOnNoexceptExpr(SourceLocation KeyLoc, SourceLocation LParen, Expr *Operand, SourceLocation RParen); @@ -5017,10 +4781,6 @@ public: Stmt *MaybeCreateStmtWithCleanups(Stmt *SubStmt); ExprResult MaybeCreateExprWithCleanups(ExprResult SubExpr); - MaterializeTemporaryExpr * - CreateMaterializeTemporaryExpr(QualType T, Expr *Temporary, - bool BoundToLvalueReference); - ExprResult ActOnFinishFullExpr(Expr *Expr) { return ActOnFinishFullExpr(Expr, Expr ? Expr->getExprLoc() : SourceLocation()); @@ -5067,41 +4827,16 @@ public: bool *CanCorrect = nullptr); NamedDecl *FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS); - /// \brief Keeps information about an identifier in a nested-name-spec. - /// - struct NestedNameSpecInfo { - /// \brief The type of the object, if we're parsing nested-name-specifier in - /// a member access expression. - ParsedType ObjectType; - - /// \brief The identifier preceding the '::'. - IdentifierInfo *Identifier; - - /// \brief The location of the identifier. - SourceLocation IdentifierLoc; - - /// \brief The location of the '::'. - SourceLocation CCLoc; - - /// \brief Creates info object for the most typical case. - NestedNameSpecInfo(IdentifierInfo *II, SourceLocation IdLoc, - SourceLocation ColonColonLoc, ParsedType ObjectType = ParsedType()) - : ObjectType(ObjectType), Identifier(II), IdentifierLoc(IdLoc), - CCLoc(ColonColonLoc) { - } - - NestedNameSpecInfo(IdentifierInfo *II, SourceLocation IdLoc, - SourceLocation ColonColonLoc, QualType ObjectType) - : ObjectType(ParsedType::make(ObjectType)), Identifier(II), - IdentifierLoc(IdLoc), CCLoc(ColonColonLoc) { - } - }; - bool isNonTypeNestedNameSpecifier(Scope *S, CXXScopeSpec &SS, - NestedNameSpecInfo &IdInfo); + SourceLocation IdLoc, + IdentifierInfo &II, + ParsedType ObjectType); bool BuildCXXNestedNameSpecifier(Scope *S, - NestedNameSpecInfo &IdInfo, + IdentifierInfo &Identifier, + SourceLocation IdentifierLoc, + SourceLocation CCLoc, + QualType ObjectType, bool EnteringContext, CXXScopeSpec &SS, NamedDecl *ScopeLookupResult, @@ -5112,8 +4847,14 @@ public: /// /// \param S The scope in which this nested-name-specifier occurs. /// - /// \param IdInfo Parser information about an identifier in the - /// nested-name-spec. + /// \param Identifier The identifier preceding the '::'. + /// + /// \param IdentifierLoc The location of the identifier. + /// + /// \param CCLoc The location of the '::'. + /// + /// \param ObjectType The type of the object, if we're parsing + /// nested-name-specifier in a member access expression. /// /// \param EnteringContext Whether we're entering the context nominated by /// this nested-name-specifier. @@ -5132,7 +4873,10 @@ public: /// /// \returns true if an error occurred, false otherwise. bool ActOnCXXNestedNameSpecifier(Scope *S, - NestedNameSpecInfo &IdInfo, + IdentifierInfo &Identifier, + SourceLocation IdentifierLoc, + SourceLocation CCLoc, + ParsedType ObjectType, bool EnteringContext, CXXScopeSpec &SS, bool ErrorRecoveryLookup = false, @@ -5145,7 +4889,10 @@ public: SourceLocation ColonColonLoc); bool IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS, - NestedNameSpecInfo &IdInfo, + IdentifierInfo &Identifier, + SourceLocation IdentifierLoc, + SourceLocation ColonLoc, + ParsedType ObjectType, bool EnteringContext); /// \brief The parser has parsed a nested-name-specifier @@ -5237,7 +4984,7 @@ public: /// \brief Create a new lambda closure type. CXXRecordDecl *createLambdaClosureType(SourceRange IntroducerRange, TypeSourceInfo *Info, - bool KnownDependent, + bool KnownDependent, LambdaCaptureDefault CaptureDefault); /// \brief Start the definition of a lambda expression. @@ -5245,11 +4992,10 @@ public: SourceRange IntroducerRange, TypeSourceInfo *MethodType, SourceLocation EndLoc, - ArrayRef<ParmVarDecl *> Params, - bool IsConstexprSpecified); + ArrayRef<ParmVarDecl *> Params); /// \brief Endow the lambda scope info with the relevant properties. - void buildLambdaScope(sema::LambdaScopeInfo *LSI, + void buildLambdaScope(sema::LambdaScopeInfo *LSI, CXXMethodDecl *CallOperator, SourceRange IntroducerRange, LambdaCaptureDefault CaptureDefault, @@ -5273,7 +5019,7 @@ public: /// \brief Create a dummy variable within the declcontext of the lambda's /// call operator, for name lookup purposes for a lambda init capture. - /// + /// /// CodeGen handles emission of lambda captures, ignoring these dummy /// variables appropriately. VarDecl *createLambdaInitCaptureVarDecl(SourceLocation Loc, @@ -5543,18 +5289,11 @@ public: ArrayRef<CXXCtorInitializer*> MemInits, bool AnyErrors); - /// \brief Check class-level dllimport/dllexport attribute. The caller must - /// ensure that referenceDLLExportedClassMethods is called some point later - /// when all outer classes of Class are complete. void checkClassLevelDLLAttribute(CXXRecordDecl *Class); - - void referenceDLLExportedClassMethods(); - void propagateDLLAttrToBaseClassTemplate( CXXRecordDecl *Class, Attr *ClassAttr, ClassTemplateSpecializationDecl *BaseTemplateSpec, SourceLocation BaseLoc); - void CheckCompletedCXXClass(CXXRecordDecl *Record); void ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc, Decl *TagDecl, @@ -5672,7 +5411,7 @@ public: /// CheckOverrideControl - Check C++11 override control semantics. void CheckOverrideControl(NamedDecl *D); - + /// DiagnoseAbsenceOfOverrideControl - Diagnose if 'override' keyword was /// not used in the declaration of an overriding method. void DiagnoseAbsenceOfOverrideControl(NamedDecl *D); @@ -5710,13 +5449,13 @@ public: bool Diagnose = true); AccessResult CheckConstructorAccess(SourceLocation Loc, CXXConstructorDecl *D, - DeclAccessPair FoundDecl, const InitializedEntity &Entity, + AccessSpecifier Access, bool IsCopyBindingRefToTemp = false); AccessResult CheckConstructorAccess(SourceLocation Loc, CXXConstructorDecl *D, - DeclAccessPair FoundDecl, const InitializedEntity &Entity, + AccessSpecifier Access, const PartialDiagnostic &PDiag); AccessResult CheckDestructorAccess(SourceLocation Loc, CXXDestructorDecl *Dtor, @@ -5814,14 +5553,6 @@ public: TemplateTy &SuggestedTemplate, TemplateNameKind &SuggestedKind); - bool DiagnoseUninstantiableTemplate(SourceLocation PointOfInstantiation, - NamedDecl *Instantiation, - bool InstantiatedFromMember, - const NamedDecl *Pattern, - const NamedDecl *PatternDef, - TemplateSpecializationKind TSK, - bool Complain = true); - void DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl); TemplateDecl *AdjustDeclIfTemplate(Decl *&Decl); @@ -5834,10 +5565,7 @@ public: SourceLocation EqualLoc, ParsedType DefaultArg); - QualType CheckNonTypeTemplateParameterType(TypeSourceInfo *&TSI, - SourceLocation Loc); QualType CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc); - Decl *ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, unsigned Depth, unsigned Position, @@ -5860,8 +5588,7 @@ public: SourceLocation TemplateLoc, SourceLocation LAngleLoc, ArrayRef<Decl *> Params, - SourceLocation RAngleLoc, - Expr *RequiresClause); + SourceLocation RAngleLoc); /// \brief The context in which we are checking a template parameter list. enum TemplateParamListContext { @@ -5896,10 +5623,6 @@ public: TemplateParameterList **OuterTemplateParamLists, SkipBodyInfo *SkipBody = nullptr); - TemplateArgumentLoc getTrivialTemplateArgumentLoc(const TemplateArgument &Arg, - QualType NTTPType, - SourceLocation Loc); - void translateTemplateArguments(const ASTTemplateArgsPtr &In, TemplateArgumentListInfo &Out); @@ -5974,15 +5697,6 @@ public: MultiTemplateParamsArg TemplateParameterLists, SkipBodyInfo *SkipBody = nullptr); - bool CheckTemplatePartialSpecializationArgs(SourceLocation Loc, - TemplateDecl *PrimaryTemplate, - unsigned NumExplicitArgs, - ArrayRef<TemplateArgument> Args); - void CheckTemplatePartialSpecialization( - ClassTemplatePartialSpecializationDecl *Partial); - void CheckTemplatePartialSpecialization( - VarTemplatePartialSpecializationDecl *Partial); - Decl *ActOnTemplateDeclarator(Scope *S, MultiTemplateParamsArg TemplateParameterLists, Declarator &D); @@ -6409,9 +6123,9 @@ public: /// \brief Collect the set of unexpanded parameter packs within the given /// nested-name-specifier. /// - /// \param NNS The nested-name-specifier that will be traversed to find + /// \param SS The nested-name-specifier that will be traversed to find /// unexpanded parameter packs. - void collectUnexpandedParameterPacks(NestedNameSpecifierLoc NNS, + void collectUnexpandedParameterPacks(CXXScopeSpec &SS, SmallVectorImpl<UnexpandedParameterPack> &Unexpanded); /// \brief Collect the set of unexpanded parameter packs within the given @@ -6555,24 +6269,11 @@ public: SourceLocation &Ellipsis, Optional<unsigned> &NumExpansions) const; - /// Given a template argument that contains an unexpanded parameter pack, but - /// which has already been substituted, attempt to determine the number of - /// elements that will be produced once this argument is fully-expanded. - /// - /// This is intended for use when transforming 'sizeof...(Arg)' in order to - /// avoid actually expanding the pack where possible. - Optional<unsigned> getFullyPackExpandedSize(TemplateArgument Arg); - //===--------------------------------------------------------------------===// // C++ Template Argument Deduction (C++ [temp.deduct]) //===--------------------------------------------------------------------===// - /// Adjust the type \p ArgFunctionType to match the calling convention, - /// noreturn, and optionally the exception specification of \p FunctionType. - /// Deduction often wants to ignore these properties when matching function - /// types. - QualType adjustCCAndNoReturn(QualType ArgFunctionType, QualType FunctionType, - bool AdjustExceptionSpec = false); + QualType adjustCCAndNoReturn(QualType ArgFunctionType, QualType FunctionType); /// \brief Describes the result of template argument deduction. /// @@ -6608,10 +6309,6 @@ public: /// \brief After substituting deduced template arguments, a dependent /// parameter type did not match the corresponding argument. TDK_DeducedMismatch, - /// \brief After substituting deduced template arguments, an element of - /// a dependent parameter type did not match the corresponding element - /// of the corresponding argument (when deducing from an initializer list). - TDK_DeducedMismatchNested, /// \brief A non-depnedent component of the parameter did not match the /// corresponding component of the argument. TDK_NonDeducedMismatch, @@ -6624,12 +6321,11 @@ public: /// \brief The explicitly-specified template arguments were not valid /// template arguments for the given template. TDK_InvalidExplicitArguments, - /// \brief Checking non-dependent argument conversions failed. - TDK_NonDependentConversionFailure, + /// \brief The arguments included an overloaded function name that could + /// not be resolved to a suitable function. + TDK_FailedOverloadResolution, /// \brief Deduction failed; that's all we know. - TDK_MiscellaneousDeductionFailure, - /// \brief CUDA Target attributes do not match. - TDK_CUDATargetMismatch + TDK_MiscellaneousDeductionFailure }; TemplateDeductionResult @@ -6652,33 +6348,33 @@ public: /// brief A function argument from which we performed template argument // deduction for a call. struct OriginalCallArg { - OriginalCallArg(QualType OriginalParamType, bool DecomposedParam, - unsigned ArgIdx, QualType OriginalArgType) - : OriginalParamType(OriginalParamType), - DecomposedParam(DecomposedParam), ArgIdx(ArgIdx), - OriginalArgType(OriginalArgType) {} + OriginalCallArg(QualType OriginalParamType, + unsigned ArgIdx, + QualType OriginalArgType) + : OriginalParamType(OriginalParamType), ArgIdx(ArgIdx), + OriginalArgType(OriginalArgType) { } QualType OriginalParamType; - bool DecomposedParam; unsigned ArgIdx; QualType OriginalArgType; }; - TemplateDeductionResult FinishTemplateArgumentDeduction( - FunctionTemplateDecl *FunctionTemplate, - SmallVectorImpl<DeducedTemplateArgument> &Deduced, - unsigned NumExplicitlySpecified, FunctionDecl *&Specialization, - sema::TemplateDeductionInfo &Info, - SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs = nullptr, - bool PartialOverloading = false, - llvm::function_ref<bool()> CheckNonDependent = []{ return false; }); + TemplateDeductionResult + FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate, + SmallVectorImpl<DeducedTemplateArgument> &Deduced, + unsigned NumExplicitlySpecified, + FunctionDecl *&Specialization, + sema::TemplateDeductionInfo &Info, + SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs = nullptr, + bool PartialOverloading = false); - TemplateDeductionResult DeduceTemplateArguments( - FunctionTemplateDecl *FunctionTemplate, - TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args, - FunctionDecl *&Specialization, sema::TemplateDeductionInfo &Info, - bool PartialOverloading, - llvm::function_ref<bool(ArrayRef<QualType>)> CheckNonDependent); + TemplateDeductionResult + DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, + TemplateArgumentListInfo *ExplicitTemplateArgs, + ArrayRef<Expr *> Args, + FunctionDecl *&Specialization, + sema::TemplateDeductionInfo &Info, + bool PartialOverloading = false); TemplateDeductionResult DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, @@ -6686,7 +6382,7 @@ public: QualType ArgFunctionType, FunctionDecl *&Specialization, sema::TemplateDeductionInfo &Info, - bool IsAddressOfFunction = false); + bool InOverloadResolution = false); TemplateDeductionResult DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, @@ -6699,12 +6395,12 @@ public: TemplateArgumentListInfo *ExplicitTemplateArgs, FunctionDecl *&Specialization, sema::TemplateDeductionInfo &Info, - bool IsAddressOfFunction = false); + bool InOverloadResolution = false); /// \brief Substitute Replacement for \p auto in \p TypeWithAuto QualType SubstAutoType(QualType TypeWithAuto, QualType Replacement); /// \brief Substitute Replacement for auto in TypeWithAuto - TypeSourceInfo* SubstAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto, + TypeSourceInfo* SubstAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto, QualType Replacement); /// \brief Result type of DeduceAutoType. @@ -6714,12 +6410,10 @@ public: DAR_FailedAlreadyDiagnosed }; - DeduceAutoResult - DeduceAutoType(TypeSourceInfo *AutoType, Expr *&Initializer, QualType &Result, - Optional<unsigned> DependentDeductionDepth = None); - DeduceAutoResult - DeduceAutoType(TypeLoc AutoTypeLoc, Expr *&Initializer, QualType &Result, - Optional<unsigned> DependentDeductionDepth = None); + DeduceAutoResult DeduceAutoType(TypeSourceInfo *AutoType, Expr *&Initializer, + QualType &Result); + DeduceAutoResult DeduceAutoType(TypeLoc AutoTypeLoc, Expr *&Initializer, + QualType &Result); void DiagnoseAutoDeductionFailure(VarDecl *VDecl, Expr *Init); bool DeduceReturnType(FunctionDecl *FD, SourceLocation Loc, bool Diagnose = true); @@ -6756,19 +6450,10 @@ public: ClassTemplatePartialSpecializationDecl *PS2, SourceLocation Loc); - bool isMoreSpecializedThanPrimary(ClassTemplatePartialSpecializationDecl *T, - sema::TemplateDeductionInfo &Info); - VarTemplatePartialSpecializationDecl *getMoreSpecializedPartialSpecialization( VarTemplatePartialSpecializationDecl *PS1, VarTemplatePartialSpecializationDecl *PS2, SourceLocation Loc); - bool isMoreSpecializedThanPrimary(VarTemplatePartialSpecializationDecl *T, - sema::TemplateDeductionInfo &Info); - - bool isTemplateTemplateParameterAtLeastAsSpecializedAs( - TemplateParameterList *P, TemplateDecl *AArg, SourceLocation Loc); - void MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs, bool OnlyDeduced, unsigned Depth, @@ -6801,10 +6486,10 @@ public: TemplateInstantiation, /// We are instantiating a default argument for a template - /// parameter. The Entity is the template parameter whose argument is - /// being instantiated, the Template is the template, and the - /// TemplateArgs/NumTemplateArguments provide the template arguments as - /// specified. + /// parameter. The Entity is the template, and + /// TemplateArgs/NumTemplateArguments provides the template + /// arguments as specified. + /// FIXME: Use a TemplateArgumentList DefaultTemplateArgumentInstantiation, /// We are instantiating a default argument for a function. @@ -6819,8 +6504,8 @@ public: /// We are substituting template argument determined as part of /// template argument deduction for either a class template /// partial specialization or a function template. The - /// Entity is either a {Class|Var}TemplatePartialSpecializationDecl or - /// a TemplateDecl. + /// Entity is either a ClassTemplatePartialSpecializationDecl or + /// a FunctionTemplateDecl. DeducedTemplateArgumentSubstitution, /// We are substituting prior template arguments into a new @@ -6855,10 +6540,6 @@ public: /// \brief The number of template arguments in TemplateArgs. unsigned NumTemplateArgs; - ArrayRef<TemplateArgument> template_arguments() const { - return {TemplateArgs, NumTemplateArgs}; - } - /// \brief The template deduction info object associated with the /// substitution or checking of explicit or deduced template arguments. sema::TemplateDeductionInfo *DeductionInfo; @@ -6919,13 +6600,6 @@ public: SmallVector<ActiveTemplateInstantiation, 16> ActiveTemplateInstantiations; - /// Specializations whose definitions are currently being instantiated. - llvm::DenseSet<std::pair<Decl *, unsigned>> InstantiatingSpecializations; - - /// Non-dependent types used in templates that have already been instantiated - /// by some template instantiation. - llvm::DenseSet<QualType> InstantiatedNonDependentTypes; - /// \brief Extra modules inspected when performing a lookup during a template /// instantiation. Computed lazily. SmallVector<Module*, 16> ActiveTemplateInstantiationLookupModules; @@ -6940,10 +6614,6 @@ public: /// template defined within it. llvm::DenseSet<Module*> &getLookupModules(); - /// \brief Map from the most recent declaration of a namespace to the most - /// recent visible declaration of that namespace. - llvm::DenseMap<NamedDecl*, NamedDecl*> VisibleNamespaceCache; - /// \brief Whether we are in a SFINAE context that is not associated with /// template instantiation. /// @@ -7032,12 +6702,12 @@ public: /// \brief Note that we are instantiating a default argument in a /// template-id. InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, - TemplateParameter Param, TemplateDecl *Template, + TemplateDecl *Template, ArrayRef<TemplateArgument> TemplateArgs, SourceRange InstantiationRange = SourceRange()); - /// \brief Note that we are substituting either explicitly-specified or - /// deduced template arguments during function template argument deduction. + /// \brief Note that we are instantiating a default argument in a + /// template-id. InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, FunctionTemplateDecl *FunctionTemplate, ArrayRef<TemplateArgument> TemplateArgs, @@ -7046,14 +6716,6 @@ public: SourceRange InstantiationRange = SourceRange()); /// \brief Note that we are instantiating as part of template - /// argument deduction for a class template declaration. - InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, - TemplateDecl *Template, - ArrayRef<TemplateArgument> TemplateArgs, - sema::TemplateDeductionInfo &DeductionInfo, - SourceRange InstantiationRange = SourceRange()); - - /// \brief Note that we are instantiating as part of template /// argument deduction for a class template partial /// specialization. InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, @@ -7112,14 +6774,9 @@ public: /// recursive template instantiations. bool isInvalid() const { return Invalid; } - /// \brief Determine whether we are already instantiating this - /// specialization in some surrounding active instantiation. - bool isAlreadyInstantiating() const { return AlreadyInstantiating; } - private: Sema &SemaRef; bool Invalid; - bool AlreadyInstantiating; bool SavedInNonInstantiationSFINAEContext; bool CheckInstantiationDepth(SourceLocation PointOfInstantiation, SourceRange InstantiationRange); @@ -7308,33 +6965,6 @@ public: SavedPendingLocalImplicitInstantiations; }; - /// A helper class for building up ExtParameterInfos. - class ExtParameterInfoBuilder { - SmallVector<FunctionProtoType::ExtParameterInfo, 16> Infos; - bool HasInteresting = false; - - public: - /// Set the ExtParameterInfo for the parameter at the given index, - /// - void set(unsigned index, FunctionProtoType::ExtParameterInfo info) { - assert(Infos.size() <= index); - Infos.resize(index); - Infos.push_back(info); - - if (!HasInteresting) - HasInteresting = (info != FunctionProtoType::ExtParameterInfo()); - } - - /// Return a pointer (suitable for setting in an ExtProtoInfo) to the - /// ExtParameterInfo array we've built up. - const FunctionProtoType::ExtParameterInfo * - getPointerOrNull(unsigned numParams) { - if (!HasInteresting) return nullptr; - Infos.resize(numParams); - return Infos.data(); - } - }; - void PerformPendingInstantiations(bool LocalOnly = false); TypeSourceInfo *SubstType(TypeSourceInfo *T, @@ -7362,12 +6992,11 @@ public: int indexAdjustment, Optional<unsigned> NumExpansions, bool ExpectParameterPack); - bool SubstParmTypes(SourceLocation Loc, ArrayRef<ParmVarDecl *> Params, - const FunctionProtoType::ExtParameterInfo *ExtParamInfos, + bool SubstParmTypes(SourceLocation Loc, + ParmVarDecl **Params, unsigned NumParams, const MultiLevelTemplateArgumentList &TemplateArgs, SmallVectorImpl<QualType> &ParamTypes, - SmallVectorImpl<ParmVarDecl *> *OutParams, - ExtParameterInfoBuilder &ParamInfos); + SmallVectorImpl<ParmVarDecl *> *OutParams = nullptr); ExprResult SubstExpr(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs); @@ -7472,8 +7101,7 @@ public: void InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, FunctionDecl *Function, bool Recursive = false, - bool DefinitionRequired = false, - bool AtEndOfTU = false); + bool DefinitionRequired = false); VarTemplateSpecializationDecl *BuildVarTemplateInstantiation( VarTemplateDecl *VarTemplate, VarDecl *FromVar, const TemplateArgumentList &TemplateArgList, @@ -7497,8 +7125,7 @@ public: const MultiLevelTemplateArgumentList &TemplateArgs); void InstantiateVariableDefinition(SourceLocation PointOfInstantiation, VarDecl *Var, bool Recursive = false, - bool DefinitionRequired = false, - bool AtEndOfTU = false); + bool DefinitionRequired = false); void InstantiateStaticDataMemberDefinition( SourceLocation PointOfInstantiation, VarDecl *Var, @@ -7554,7 +7181,7 @@ public: const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc, AttributeList *AttrList); - + void ActOnSuperClassOfClassInterface(Scope *S, SourceLocation AtInterfaceLoc, ObjCInterfaceDecl *IDecl, @@ -7564,9 +7191,8 @@ public: SourceLocation SuperLoc, ArrayRef<ParsedType> SuperTypeArgs, SourceRange SuperTypeArgsRange); - + void ActOnTypedefedProtocols(SmallVectorImpl<Decl *> &ProtocolRefs, - SmallVectorImpl<SourceLocation> &ProtocolLocs, IdentifierInfo *SuperName, SourceLocation SuperLoc); @@ -7628,12 +7254,6 @@ public: ArrayRef<IdentifierLocPair> ProtocolId, SmallVectorImpl<Decl *> &Protocols); - void DiagnoseTypeArgsAndProtocols(IdentifierInfo *ProtocolId, - SourceLocation ProtocolLoc, - IdentifierInfo *TypeArgId, - SourceLocation TypeArgLoc, - bool SelectProtocolFirst = false); - /// Given a list of identifiers (and their locations), resolve the /// names to either Objective-C protocol qualifiers or type /// arguments, as appropriate. @@ -7673,14 +7293,6 @@ public: ArrayRef<SourceLocation> ProtocolLocs, SourceLocation ProtocolRAngleLoc); - /// Build an Objective-C type parameter type. - QualType BuildObjCTypeParamType(const ObjCTypeParamDecl *Decl, - SourceLocation ProtocolLAngleLoc, - ArrayRef<ObjCProtocolDecl *> Protocols, - ArrayRef<SourceLocation> ProtocolLocs, - SourceLocation ProtocolRAngleLoc, - bool FailOnError = false); - /// Build an Objective-C object pointer type. QualType BuildObjCObjectType(QualType BaseType, SourceLocation Loc, @@ -7736,8 +7348,7 @@ public: bool ImplKind, IdentifierInfo *PropertyId, IdentifierInfo *PropertyIvar, - SourceLocation PropertyIvarLoc, - ObjCPropertyQueryKind QueryKind); + SourceLocation PropertyIvarLoc); enum ObjCSpecialMethodKind { OSMK_None, @@ -7891,14 +7502,14 @@ public: ParsedType Type, SourceLocation RParenLoc, Expr *SubExpr); - + void CheckTollFreeBridgeCast(QualType castType, Expr *castExpr); - + void CheckObjCBridgeRelatedCast(QualType castType, Expr *castExpr); - + bool CheckTollFreeBridgeStaticCast(QualType castType, Expr *castExpr, CastKind &Kind); - + bool checkObjCBridgeRelatedComponents(SourceLocation Loc, QualType DestType, QualType SrcType, ObjCInterfaceDecl *&RelatedClass, @@ -7945,17 +7556,41 @@ public: void ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind, SourceLocation PragmaLoc); + enum PragmaPackKind { + PPK_Default, // #pragma pack([n]) + PPK_Show, // #pragma pack(show), only supported by MSVC. + PPK_Push, // #pragma pack(push, [identifier], [n]) + PPK_Pop // #pragma pack(pop, [identifier], [n]) + }; + + enum PragmaMSStructKind { + PMSST_OFF, // #pragms ms_struct off + PMSST_ON // #pragms ms_struct on + }; + + enum PragmaMSCommentKind { + PCK_Unknown, + PCK_Linker, // #pragma comment(linker, ...) + PCK_Lib, // #pragma comment(lib, ...) + PCK_Compiler, // #pragma comment(compiler, ...) + PCK_ExeStr, // #pragma comment(exestr, ...) + PCK_User // #pragma comment(user, ...) + }; + /// ActOnPragmaPack - Called on well formed \#pragma pack(...). - void ActOnPragmaPack(SourceLocation PragmaLoc, PragmaMsStackAction Action, - StringRef SlotLabel, Expr *Alignment); + void ActOnPragmaPack(PragmaPackKind Kind, + IdentifierInfo *Name, + Expr *Alignment, + SourceLocation PragmaLoc, + SourceLocation LParenLoc, + SourceLocation RParenLoc); /// ActOnPragmaMSStruct - Called on well formed \#pragma ms_struct [on|off]. void ActOnPragmaMSStruct(PragmaMSStructKind Kind); /// ActOnPragmaMSComment - Called on well formed /// \#pragma comment(kind, "arg"). - void ActOnPragmaMSComment(SourceLocation CommentLoc, PragmaMSCommentKind Kind, - StringRef Arg); + void ActOnPragmaMSComment(PragmaMSCommentKind Kind, StringRef Arg); /// ActOnPragmaMSPointersToMembers - called on well formed \#pragma /// pointers_to_members(representation method[, general purpose @@ -7965,8 +7600,7 @@ public: SourceLocation PragmaLoc); /// \brief Called on well formed \#pragma vtordisp(). - void ActOnPragmaMSVtorDisp(PragmaMsStackAction Action, - SourceLocation PragmaLoc, + void ActOnPragmaMSVtorDisp(PragmaVtorDispKind Kind, SourceLocation PragmaLoc, MSVtorDispAttr::Mode Value); enum PragmaSectionKind { @@ -8002,8 +7636,7 @@ public: void ActOnPragmaDump(Scope *S, SourceLocation Loc, IdentifierInfo *II); /// ActOnPragmaDetectMismatch - Call on well-formed \#pragma detect_mismatch - void ActOnPragmaDetectMismatch(SourceLocation Loc, StringRef Name, - StringRef Value); + void ActOnPragmaDetectMismatch(StringRef Name, StringRef Value); /// ActOnPragmaUnused - Called on well-formed '\#pragma unused'. void ActOnPragmaUnused(const Token &Identifier, @@ -8113,17 +7746,6 @@ public: void AddLaunchBoundsAttr(SourceRange AttrRange, Decl *D, Expr *MaxThreads, Expr *MinBlocks, unsigned SpellingListIndex); - /// AddModeAttr - Adds a mode attribute to a particular declaration. - void AddModeAttr(SourceRange AttrRange, Decl *D, IdentifierInfo *Name, - unsigned SpellingListIndex, bool InInstantiation = false); - - void AddParameterABIAttr(SourceRange AttrRange, Decl *D, - ParameterABI ABI, unsigned SpellingListIndex); - - void AddNSConsumedAttr(SourceRange AttrRange, Decl *D, - unsigned SpellingListIndex, bool isNSConsumed, - bool isTemplateInstantiation); - //===--------------------------------------------------------------------===// // C++ Coroutines TS // @@ -8138,111 +7760,38 @@ public: void CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body); //===--------------------------------------------------------------------===// - // OpenCL extensions. - // -private: - std::string CurrOpenCLExtension; - /// Extensions required by an OpenCL type. - llvm::DenseMap<const Type*, std::set<std::string>> OpenCLTypeExtMap; - /// Extensions required by an OpenCL declaration. - llvm::DenseMap<const Decl*, std::set<std::string>> OpenCLDeclExtMap; -public: - llvm::StringRef getCurrentOpenCLExtension() const { - return CurrOpenCLExtension; - } - void setCurrentOpenCLExtension(llvm::StringRef Ext) { - CurrOpenCLExtension = Ext; - } - - /// \brief Set OpenCL extensions for a type which can only be used when these - /// OpenCL extensions are enabled. If \p Exts is empty, do nothing. - /// \param Exts A space separated list of OpenCL extensions. - void setOpenCLExtensionForType(QualType T, llvm::StringRef Exts); - - /// \brief Set OpenCL extensions for a declaration which can only be - /// used when these OpenCL extensions are enabled. If \p Exts is empty, do - /// nothing. - /// \param Exts A space separated list of OpenCL extensions. - void setOpenCLExtensionForDecl(Decl *FD, llvm::StringRef Exts); - - /// \brief Set current OpenCL extensions for a type which can only be used - /// when these OpenCL extensions are enabled. If current OpenCL extension is - /// empty, do nothing. - void setCurrentOpenCLExtensionForType(QualType T); - - /// \brief Set current OpenCL extensions for a declaration which - /// can only be used when these OpenCL extensions are enabled. If current - /// OpenCL extension is empty, do nothing. - void setCurrentOpenCLExtensionForDecl(Decl *FD); - - bool isOpenCLDisabledDecl(Decl *FD); - - /// \brief Check if type \p T corresponding to declaration specifier \p DS - /// is disabled due to required OpenCL extensions being disabled. If so, - /// emit diagnostics. - /// \return true if type is disabled. - bool checkOpenCLDisabledTypeDeclSpec(const DeclSpec &DS, QualType T); - - /// \brief Check if declaration \p D used by expression \p E - /// is disabled due to required OpenCL extensions being disabled. If so, - /// emit diagnostics. - /// \return true if type is disabled. - bool checkOpenCLDisabledDecl(const Decl &D, const Expr &E); - - //===--------------------------------------------------------------------===// // OpenMP directives and clauses. // private: void *VarDataSharingAttributesStack; - /// Set to true inside '#pragma omp declare target' region. - bool IsInOpenMPDeclareTargetContext = false; /// \brief Initialization of data-sharing attributes stack. void InitDataSharingAttributesStack(); void DestroyDataSharingAttributesStack(); ExprResult VerifyPositiveIntegerConstantInClause(Expr *Op, OpenMPClauseKind CKind, bool StrictlyPositive = true); - /// Returns OpenMP nesting level for current directive. - unsigned getOpenMPNestingLevel() const; - - /// Checks if a type or a declaration is disabled due to the owning extension - /// being disabled, and emits diagnostic messages if it is disabled. - /// \param D type or declaration to be checked. - /// \param DiagLoc source location for the diagnostic message. - /// \param DiagInfo information to be emitted for the diagnostic message. - /// \param SrcRange source range of the declaration. - /// \param Map maps type or declaration to the extensions. - /// \param Selector selects diagnostic message: 0 for type and 1 for - /// declaration. - /// \return true if the type or declaration is disabled. - template <typename T, typename DiagLocT, typename DiagInfoT, typename MapT> - bool checkOpenCLDisabledTypeOrDecl(T D, DiagLocT DiagLoc, DiagInfoT DiagInfo, - MapT &Map, unsigned Selector = 0, - SourceRange SrcRange = SourceRange()); public: /// \brief Return true if the provided declaration \a VD should be captured by - /// reference. - /// \param Level Relative level of nested OpenMP construct for that the check - /// is performed. - bool IsOpenMPCapturedByRef(ValueDecl *D, unsigned Level); + /// reference in the provided scope \a RSI. This will take into account the + /// semantics of the directive and associated clauses. + bool IsOpenMPCapturedByRef(VarDecl *VD, + const sema::CapturedRegionScopeInfo *RSI); /// \brief Check if the specified variable is used in one of the private /// clauses (private, firstprivate, lastprivate, reduction etc.) in OpenMP /// constructs. - VarDecl *IsOpenMPCapturedDecl(ValueDecl *D); - ExprResult getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK, - ExprObjectKind OK, SourceLocation Loc); + bool IsOpenMPCapturedVar(VarDecl *VD); /// \brief Check if the specified variable is used in 'private' clause. /// \param Level Relative level of nested OpenMP construct for that the check /// is performed. - bool isOpenMPPrivateDecl(ValueDecl *D, unsigned Level); + bool isOpenMPPrivateVar(VarDecl *VD, unsigned Level); /// \brief Check if the specified variable is captured by 'target' directive. /// \param Level Relative level of nested OpenMP construct for that the check /// is performed. - bool isOpenMPTargetCapturedDecl(ValueDecl *D, unsigned Level); + bool isOpenMPTargetCapturedVar(VarDecl *VD, unsigned Level); ExprResult PerformOpenMPImplicitIntegerConversion(SourceLocation OpLoc, Expr *Op); @@ -8277,42 +7826,6 @@ public: OMPThreadPrivateDecl *CheckOMPThreadPrivateDecl( SourceLocation Loc, ArrayRef<Expr *> VarList); - /// \brief Check if the specified type is allowed to be used in 'omp declare - /// reduction' construct. - QualType ActOnOpenMPDeclareReductionType(SourceLocation TyLoc, - TypeResult ParsedType); - /// \brief Called on start of '#pragma omp declare reduction'. - DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveStart( - Scope *S, DeclContext *DC, DeclarationName Name, - ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes, - AccessSpecifier AS, Decl *PrevDeclInScope = nullptr); - /// \brief Initialize declare reduction construct initializer. - void ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D); - /// \brief Finish current declare reduction construct initializer. - void ActOnOpenMPDeclareReductionCombinerEnd(Decl *D, Expr *Combiner); - /// \brief Initialize declare reduction construct initializer. - void ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D); - /// \brief Finish current declare reduction construct initializer. - void ActOnOpenMPDeclareReductionInitializerEnd(Decl *D, Expr *Initializer); - /// \brief Called at the end of '#pragma omp declare reduction'. - DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveEnd( - Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid); - - /// Called on the start of target region i.e. '#pragma omp declare target'. - bool ActOnStartOpenMPDeclareTargetDirective(SourceLocation Loc); - /// Called at the end of target region i.e. '#pragme omp end declare target'. - void ActOnFinishOpenMPDeclareTargetDirective(); - /// Called on correct id-expression from the '#pragma omp declare target'. - void ActOnOpenMPDeclareTargetName(Scope *CurScope, CXXScopeSpec &ScopeSpec, - const DeclarationNameInfo &Id, - OMPDeclareTargetDeclAttr::MapTypeTy MT, - NamedDeclSetType &SameDirectiveDecls); - /// Check declaration inside target region. - void checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D); - /// Return true inside OpenMP target region. - bool isInOpenMPDeclareTargetContext() const { - return IsInOpenMPDeclareTargetContext; - } /// \brief Initialization of captured region for OpenMP region. void ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope); @@ -8338,19 +7851,19 @@ public: StmtResult ActOnOpenMPSimdDirective( ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, - llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA); + llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA); /// \brief Called on well-formed '\#pragma omp for' after parsing /// of the associated statement. StmtResult ActOnOpenMPForDirective( ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, - llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA); + llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA); /// \brief Called on well-formed '\#pragma omp for simd' after parsing /// of the associated statement. StmtResult ActOnOpenMPForSimdDirective( ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, - llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA); + llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA); /// \brief Called on well-formed '\#pragma omp sections' after parsing /// of the associated statement. StmtResult ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses, @@ -8380,13 +7893,13 @@ public: StmtResult ActOnOpenMPParallelForDirective( ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, - llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA); + llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA); /// \brief Called on well-formed '\#pragma omp parallel for simd' after /// parsing of the associated statement. StmtResult ActOnOpenMPParallelForSimdDirective( ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, - llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA); + llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA); /// \brief Called on well-formed '\#pragma omp parallel sections' after /// parsing of the associated statement. StmtResult ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause *> Clauses, @@ -8434,28 +7947,6 @@ public: StmtResult ActOnOpenMPTargetDataDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc); - /// \brief Called on well-formed '\#pragma omp target enter data' after - /// parsing of the associated statement. - StmtResult ActOnOpenMPTargetEnterDataDirective(ArrayRef<OMPClause *> Clauses, - SourceLocation StartLoc, - SourceLocation EndLoc); - /// \brief Called on well-formed '\#pragma omp target exit data' after - /// parsing of the associated statement. - StmtResult ActOnOpenMPTargetExitDataDirective(ArrayRef<OMPClause *> Clauses, - SourceLocation StartLoc, - SourceLocation EndLoc); - /// \brief Called on well-formed '\#pragma omp target parallel' after - /// parsing of the associated statement. - StmtResult ActOnOpenMPTargetParallelDirective(ArrayRef<OMPClause *> Clauses, - Stmt *AStmt, - SourceLocation StartLoc, - SourceLocation EndLoc); - /// \brief Called on well-formed '\#pragma omp target parallel for' after - /// parsing of the associated statement. - StmtResult ActOnOpenMPTargetParallelForDirective( - ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, - llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA); /// \brief Called on well-formed '\#pragma omp teams' after parsing of the /// associated statement. StmtResult ActOnOpenMPTeamsDirective(ArrayRef<OMPClause *> Clauses, @@ -8476,123 +7967,19 @@ public: StmtResult ActOnOpenMPTaskLoopDirective( ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, - llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA); + llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA); /// \brief Called on well-formed '\#pragma omp taskloop simd' after parsing of /// the associated statement. StmtResult ActOnOpenMPTaskLoopSimdDirective( ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, - llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA); + llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA); /// \brief Called on well-formed '\#pragma omp distribute' after parsing /// of the associated statement. StmtResult ActOnOpenMPDistributeDirective( ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, - llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA); - /// \brief Called on well-formed '\#pragma omp target update'. - StmtResult ActOnOpenMPTargetUpdateDirective(ArrayRef<OMPClause *> Clauses, - SourceLocation StartLoc, - SourceLocation EndLoc); - /// \brief Called on well-formed '\#pragma omp distribute parallel for' after - /// parsing of the associated statement. - StmtResult ActOnOpenMPDistributeParallelForDirective( - ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, - llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA); - /// \brief Called on well-formed '\#pragma omp distribute parallel for simd' - /// after parsing of the associated statement. - StmtResult ActOnOpenMPDistributeParallelForSimdDirective( - ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, - llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA); - /// \brief Called on well-formed '\#pragma omp distribute simd' after - /// parsing of the associated statement. - StmtResult ActOnOpenMPDistributeSimdDirective( - ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, - llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA); - /// \brief Called on well-formed '\#pragma omp target parallel for simd' after - /// parsing of the associated statement. - StmtResult ActOnOpenMPTargetParallelForSimdDirective( - ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, - llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA); - /// \brief Called on well-formed '\#pragma omp target simd' after parsing of - /// the associated statement. - StmtResult ActOnOpenMPTargetSimdDirective( - ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, - llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA); - /// Called on well-formed '\#pragma omp teams distribute' after parsing of - /// the associated statement. - StmtResult ActOnOpenMPTeamsDistributeDirective( - ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, - llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA); - /// Called on well-formed '\#pragma omp teams distribute simd' after parsing - /// of the associated statement. - StmtResult ActOnOpenMPTeamsDistributeSimdDirective( - ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, - llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA); - /// Called on well-formed '\#pragma omp teams distribute parallel for simd' - /// after parsing of the associated statement. - StmtResult ActOnOpenMPTeamsDistributeParallelForSimdDirective( - ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, - llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA); - /// Called on well-formed '\#pragma omp teams distribute parallel for' - /// after parsing of the associated statement. - StmtResult ActOnOpenMPTeamsDistributeParallelForDirective( - ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, - llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA); - /// Called on well-formed '\#pragma omp target teams' after parsing of the - /// associated statement. - StmtResult ActOnOpenMPTargetTeamsDirective(ArrayRef<OMPClause *> Clauses, - Stmt *AStmt, - SourceLocation StartLoc, - SourceLocation EndLoc); - /// Called on well-formed '\#pragma omp target teams distribute' after parsing - /// of the associated statement. - StmtResult ActOnOpenMPTargetTeamsDistributeDirective( - ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, - llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA); - /// Called on well-formed '\#pragma omp target teams distribute parallel for' - /// after parsing of the associated statement. - StmtResult ActOnOpenMPTargetTeamsDistributeParallelForDirective( - ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, - llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA); - /// Called on well-formed '\#pragma omp target teams distribute parallel for - /// simd' after parsing of the associated statement. - StmtResult ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective( - ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, - llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA); - /// Called on well-formed '\#pragma omp target teams distribute simd' after - /// parsing of the associated statement. - StmtResult ActOnOpenMPTargetTeamsDistributeSimdDirective( - ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, - llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA); - - /// Checks correctness of linear modifiers. - bool CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind, - SourceLocation LinLoc); - /// Checks that the specified declaration matches requirements for the linear - /// decls. - bool CheckOpenMPLinearDecl(ValueDecl *D, SourceLocation ELoc, - OpenMPLinearClauseKind LinKind, QualType Type); - - /// \brief Called on well-formed '\#pragma omp declare simd' after parsing of - /// the associated method/function. - DeclGroupPtrTy ActOnOpenMPDeclareSimdDirective( - DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, - Expr *Simdlen, ArrayRef<Expr *> Uniforms, ArrayRef<Expr *> Aligneds, - ArrayRef<Expr *> Alignments, ArrayRef<Expr *> Linears, - ArrayRef<unsigned> LinModifiers, ArrayRef<Expr *> Steps, SourceRange SR); + llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA); OMPClause *ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, @@ -8721,8 +8108,7 @@ public: CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, OpenMPDependClauseKind DepKind, OpenMPLinearClauseKind LinKind, OpenMPMapClauseKind MapTypeModifier, - OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, - SourceLocation DepLinMapLoc); + OpenMPMapClauseKind MapType, SourceLocation DepLinMapLoc); /// \brief Called on well-formed 'private' clause. OMPClause *ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList, SourceLocation StartLoc, @@ -8744,12 +8130,12 @@ public: SourceLocation LParenLoc, SourceLocation EndLoc); /// \brief Called on well-formed 'reduction' clause. - OMPClause *ActOnOpenMPReductionClause( - ArrayRef<Expr *> VarList, SourceLocation StartLoc, - SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, - CXXScopeSpec &ReductionIdScopeSpec, - const DeclarationNameInfo &ReductionId, - ArrayRef<Expr *> UnresolvedReductions = llvm::None); + OMPClause * + ActOnOpenMPReductionClause(ArrayRef<Expr *> VarList, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation ColonLoc, + SourceLocation EndLoc, + CXXScopeSpec &ReductionIdScopeSpec, + const DeclarationNameInfo &ReductionId); /// \brief Called on well-formed 'linear' clause. OMPClause * ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step, @@ -8789,12 +8175,10 @@ public: SourceLocation LParenLoc, SourceLocation EndLoc); /// \brief Called on well-formed 'map' clause. - OMPClause * - ActOnOpenMPMapClause(OpenMPMapClauseKind MapTypeModifier, - OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, - SourceLocation MapLoc, SourceLocation ColonLoc, - ArrayRef<Expr *> VarList, SourceLocation StartLoc, - SourceLocation LParenLoc, SourceLocation EndLoc); + OMPClause *ActOnOpenMPMapClause( + OpenMPMapClauseKind MapTypeModifier, OpenMPMapClauseKind MapType, + SourceLocation MapLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VarList, + SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc); /// \brief Called on well-formed 'num_teams' clause. OMPClause *ActOnOpenMPNumTeamsClause(Expr *NumTeams, SourceLocation StartLoc, SourceLocation LParenLoc, @@ -8808,36 +8192,6 @@ public: OMPClause *ActOnOpenMPPriorityClause(Expr *Priority, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc); - /// \brief Called on well-formed 'dist_schedule' clause. - OMPClause *ActOnOpenMPDistScheduleClause( - OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, - SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation KindLoc, - SourceLocation CommaLoc, SourceLocation EndLoc); - /// \brief Called on well-formed 'defaultmap' clause. - OMPClause *ActOnOpenMPDefaultmapClause( - OpenMPDefaultmapClauseModifier M, OpenMPDefaultmapClauseKind Kind, - SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc, - SourceLocation KindLoc, SourceLocation EndLoc); - /// \brief Called on well-formed 'to' clause. - OMPClause *ActOnOpenMPToClause(ArrayRef<Expr *> VarList, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc); - /// \brief Called on well-formed 'from' clause. - OMPClause *ActOnOpenMPFromClause(ArrayRef<Expr *> VarList, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc); - /// Called on well-formed 'use_device_ptr' clause. - OMPClause *ActOnOpenMPUseDevicePtrClause(ArrayRef<Expr *> VarList, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc); - /// Called on well-formed 'is_device_ptr' clause. - OMPClause *ActOnOpenMPIsDevicePtrClause(ArrayRef<Expr *> VarList, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc); /// \brief The kind of conversion being performed. enum CheckedConversionKind { @@ -8898,11 +8252,6 @@ public: // argument, and arguments that have type float are promoted to double. ExprResult DefaultArgumentPromotion(Expr *E); - /// If \p E is a prvalue denoting an unmaterialized temporary, materialize - /// it as an xvalue. In C++98, the result will still be a prvalue, because - /// we don't have xvalues there. - ExprResult TemporaryMaterializationConversion(Expr *E); - // Used for emitting the right warning by DefaultVariadicArgumentPromotion enum VariadicCallType { VariadicFunction, @@ -8984,8 +8333,8 @@ public: /// are not compatible, but we accept them as an extension. IncompatiblePointer, - /// IncompatiblePointerSign - The assignment is between two pointers types - /// which point to integers which have a different sign, but are otherwise + /// IncompatiblePointer - The assignment is between two pointers types which + /// point to integers which have a different sign, but are otherwise /// identical. This is a subset of the above, but broken out because it's by /// far the most common case of incompatible pointers. IncompatiblePointerSign, @@ -9066,23 +8415,15 @@ public: CastKind &Kind, bool ConvertRHS = true); - /// Check assignment constraints for an assignment of RHS to LHSType. - /// - /// \param LHSType The destination type for the assignment. - /// \param RHS The source expression for the assignment. - /// \param Diagnose If \c true, diagnostics may be produced when checking - /// for assignability. If a diagnostic is produced, \p RHS will be - /// set to ExprError(). Note that this function may still return - /// without producing a diagnostic, even for an invalid assignment. - /// \param DiagnoseCFAudited If \c true, the target is a function parameter - /// in an audited Core Foundation API and does not need to be checked - /// for ARC retain issues. - /// \param ConvertRHS If \c true, \p RHS will be updated to model the - /// conversions necessary to perform the assignment. If \c false, - /// \p Diagnose must also be \c false. - AssignConvertType CheckSingleAssignmentConstraints( - QualType LHSType, ExprResult &RHS, bool Diagnose = true, - bool DiagnoseCFAudited = false, bool ConvertRHS = true); + // CheckSingleAssignmentConstraints - Currently used by + // CheckAssignmentOperands, and ActOnReturnStmt. Prior to type checking, + // this routine performs the default function/array converions, if ConvertRHS + // is true. + AssignConvertType CheckSingleAssignmentConstraints(QualType LHSType, + ExprResult &RHS, + bool Diagnose = true, + bool DiagnoseCFAudited = false, + bool ConvertRHS = true); // \brief If the lhs type is a transparent union, check whether we // can initialize the transparent union with the given expression. @@ -9138,8 +8479,8 @@ public: ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, BinaryOperatorKind Opc, bool isRelational); QualType CheckBitwiseOperands( // C99 6.5.[10...12] - ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, - BinaryOperatorKind Opc); + ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, + bool IsCompAssign = false); QualType CheckLogicalOperands( // C99 6.5.[13,14] ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, BinaryOperatorKind Opc); @@ -9164,13 +8505,13 @@ public: ExprResult &cond, ExprResult &lhs, ExprResult &rhs, ExprValueKind &VK, ExprObjectKind &OK, SourceLocation questionLoc); QualType FindCompositePointerType(SourceLocation Loc, Expr *&E1, Expr *&E2, - bool ConvertArgs = true); + bool *NonStandardCompositeType = nullptr); QualType FindCompositePointerType(SourceLocation Loc, ExprResult &E1, ExprResult &E2, - bool ConvertArgs = true) { + bool *NonStandardCompositeType = nullptr) { Expr *E1Tmp = E1.get(), *E2Tmp = E2.get(); - QualType Composite = - FindCompositePointerType(Loc, E1Tmp, E2Tmp, ConvertArgs); + QualType Composite = FindCompositePointerType(Loc, E1Tmp, E2Tmp, + NonStandardCompositeType); E1 = E1Tmp; E2 = E2Tmp; return Composite; @@ -9215,7 +8556,13 @@ public: /// that their unqualified forms (T1 and T2) are either the same /// or T1 is a base class of T2. Ref_Related, - /// Ref_Compatible - The two types are reference-compatible. + /// Ref_Compatible_With_Added_Qualification - The two types are + /// reference-compatible with added qualification, meaning that + /// they are reference-compatible and the qualifiers on T1 (cv1) + /// are greater than the qualifiers on T2 (cv2). + Ref_Compatible_With_Added_Qualification, + /// Ref_Compatible - The two types are reference-compatible and + /// have equivalent qualifiers (cv1 == cv2). Ref_Compatible }; @@ -9262,7 +8609,7 @@ public: Expr *CastExpr, SourceLocation RParenLoc); - enum ARCConversionResult { ACR_okay, ACR_unbridged, ACR_error }; + enum ARCConversionResult { ACR_okay, ACR_unbridged }; /// \brief Checks for invalid conversions and casts between /// retainable pointers and other pointer kinds. @@ -9323,60 +8670,6 @@ public: /// type, and if so, emit a note describing what happened. void EmitRelatedResultTypeNoteForReturn(QualType destType); - class ConditionResult { - Decl *ConditionVar; - FullExprArg Condition; - bool Invalid; - bool HasKnownValue; - bool KnownValue; - - friend class Sema; - ConditionResult(Sema &S, Decl *ConditionVar, FullExprArg Condition, - bool IsConstexpr) - : ConditionVar(ConditionVar), Condition(Condition), Invalid(false), - HasKnownValue(IsConstexpr && Condition.get() && - !Condition.get()->isValueDependent()), - KnownValue(HasKnownValue && - !!Condition.get()->EvaluateKnownConstInt(S.Context)) {} - explicit ConditionResult(bool Invalid) - : ConditionVar(nullptr), Condition(nullptr), Invalid(Invalid), - HasKnownValue(false), KnownValue(false) {} - - public: - ConditionResult() : ConditionResult(false) {} - bool isInvalid() const { return Invalid; } - std::pair<VarDecl *, Expr *> get() const { - return std::make_pair(cast_or_null<VarDecl>(ConditionVar), - Condition.get()); - } - llvm::Optional<bool> getKnownValue() const { - if (!HasKnownValue) - return None; - return KnownValue; - } - }; - static ConditionResult ConditionError() { return ConditionResult(true); } - - enum class ConditionKind { - Boolean, ///< A boolean condition, from 'if', 'while', 'for', or 'do'. - ConstexprIf, ///< A constant boolean condition from 'if constexpr'. - Switch ///< An integral condition for a 'switch' statement. - }; - - ConditionResult ActOnCondition(Scope *S, SourceLocation Loc, - Expr *SubExpr, ConditionKind CK); - - ConditionResult ActOnConditionVariable(Decl *ConditionVar, - SourceLocation StmtLoc, - ConditionKind CK); - - DeclResult ActOnCXXConditionDeclaration(Scope *S, Declarator &D); - - ExprResult CheckConditionVariable(VarDecl *ConditionVar, - SourceLocation StmtLoc, - ConditionKind CK); - ExprResult CheckSwitchCondition(SourceLocation SwitchLoc, Expr *Cond); - /// CheckBooleanCondition - Diagnose problems involving the use of /// the given expression as a boolean condition (e.g. in an if /// statement). Also performs the standard function and array @@ -9385,8 +8678,10 @@ public: /// \param Loc - A location associated with the condition, e.g. the /// 'if' keyword. /// \return true iff there were any errors - ExprResult CheckBooleanCondition(SourceLocation Loc, Expr *E, - bool IsConstexpr = false); + ExprResult CheckBooleanCondition(Expr *E, SourceLocation Loc); + + ExprResult ActOnBooleanCondition(Scope *S, SourceLocation Loc, + Expr *SubExpr); /// DiagnoseAssignmentAsCondition - Given that an expression is /// being used as a boolean condition, warn if it's an assignment. @@ -9397,7 +8692,7 @@ public: void DiagnoseEqualityWithExtraParens(ParenExpr *ParenE); /// CheckCXXBooleanCondition - Returns true if conversion to bool is invalid. - ExprResult CheckCXXBooleanCondition(Expr *CondExpr, bool IsConstexpr = false); + ExprResult CheckCXXBooleanCondition(Expr *CondExpr); /// ConvertIntegerToTypeWarnOnOverflow - Convert the specified APInt to have /// the specified width and sign. If an overflow occurs, detect it and emit @@ -9444,154 +8739,6 @@ public: QualType FieldTy, bool IsMsStruct, Expr *BitWidth, bool *ZeroWidth = nullptr); -private: - unsigned ForceCUDAHostDeviceDepth = 0; - -public: - /// Increments our count of the number of times we've seen a pragma forcing - /// functions to be __host__ __device__. So long as this count is greater - /// than zero, all functions encountered will be __host__ __device__. - void PushForceCUDAHostDevice(); - - /// Decrements our count of the number of times we've seen a pragma forcing - /// functions to be __host__ __device__. Returns false if the count is 0 - /// before incrementing, so you can emit an error. - bool PopForceCUDAHostDevice(); - - /// Diagnostics that are emitted only if we discover that the given function - /// must be codegen'ed. Because handling these correctly adds overhead to - /// compilation, this is currently only enabled for CUDA compilations. - llvm::DenseMap<CanonicalDeclPtr<FunctionDecl>, - std::vector<PartialDiagnosticAt>> - CUDADeferredDiags; - - /// A pair of a canonical FunctionDecl and a SourceLocation. When used as the - /// key in a hashtable, both the FD and location are hashed. - struct FunctionDeclAndLoc { - CanonicalDeclPtr<FunctionDecl> FD; - SourceLocation Loc; - }; - - /// FunctionDecls and SourceLocations for which CheckCUDACall has emitted a - /// (maybe deferred) "bad call" diagnostic. We use this to avoid emitting the - /// same deferred diag twice. - llvm::DenseSet<FunctionDeclAndLoc> LocsWithCUDACallDiags; - - /// An inverse call graph, mapping known-emitted functions to one of their - /// known-emitted callers (plus the location of the call). - /// - /// Functions that we can tell a priori must be emitted aren't added to this - /// map. - llvm::DenseMap</* Callee = */ CanonicalDeclPtr<FunctionDecl>, - /* Caller = */ FunctionDeclAndLoc> - CUDAKnownEmittedFns; - - /// A partial call graph maintained during CUDA compilation to support - /// deferred diagnostics. - /// - /// Functions are only added here if, at the time they're considered, they are - /// not known-emitted. As soon as we discover that a function is - /// known-emitted, we remove it and everything it transitively calls from this - /// set and add those functions to CUDAKnownEmittedFns. - llvm::DenseMap</* Caller = */ CanonicalDeclPtr<FunctionDecl>, - /* Callees = */ llvm::MapVector<CanonicalDeclPtr<FunctionDecl>, - SourceLocation>> - CUDACallGraph; - - /// Diagnostic builder for CUDA errors which may or may not be deferred. - /// - /// In CUDA, there exist constructs (e.g. variable-length arrays, try/catch) - /// which are not allowed to appear inside __device__ functions and are - /// allowed to appear in __host__ __device__ functions only if the host+device - /// function is never codegen'ed. - /// - /// To handle this, we use the notion of "deferred diagnostics", where we - /// attach a diagnostic to a FunctionDecl that's emitted iff it's codegen'ed. - /// - /// This class lets you emit either a regular diagnostic, a deferred - /// diagnostic, or no diagnostic at all, according to an argument you pass to - /// its constructor, thus simplifying the process of creating these "maybe - /// deferred" diagnostics. - class CUDADiagBuilder { - public: - enum Kind { - /// Emit no diagnostics. - K_Nop, - /// Emit the diagnostic immediately (i.e., behave like Sema::Diag()). - K_Immediate, - /// Emit the diagnostic immediately, and, if it's a warning or error, also - /// emit a call stack showing how this function can be reached by an a - /// priori known-emitted function. - K_ImmediateWithCallStack, - /// Create a deferred diagnostic, which is emitted only if the function - /// it's attached to is codegen'ed. Also emit a call stack as with - /// K_ImmediateWithCallStack. - K_Deferred - }; - - CUDADiagBuilder(Kind K, SourceLocation Loc, unsigned DiagID, - FunctionDecl *Fn, Sema &S); - ~CUDADiagBuilder(); - - /// Convertible to bool: True if we immediately emitted an error, false if - /// we didn't emit an error or we created a deferred error. - /// - /// Example usage: - /// - /// if (CUDADiagBuilder(...) << foo << bar) - /// return ExprError(); - /// - /// But see CUDADiagIfDeviceCode() and CUDADiagIfHostCode() -- you probably - /// want to use these instead of creating a CUDADiagBuilder yourself. - operator bool() const { return ImmediateDiag.hasValue(); } - - template <typename T> - friend const CUDADiagBuilder &operator<<(const CUDADiagBuilder &Diag, - const T &Value) { - if (Diag.ImmediateDiag.hasValue()) - *Diag.ImmediateDiag << Value; - else if (Diag.PartialDiag.hasValue()) - *Diag.PartialDiag << Value; - return Diag; - } - - private: - Sema &S; - SourceLocation Loc; - unsigned DiagID; - FunctionDecl *Fn; - bool ShowCallStack; - - // Invariant: At most one of these Optionals has a value. - // FIXME: Switch these to a Variant once that exists. - llvm::Optional<SemaDiagnosticBuilder> ImmediateDiag; - llvm::Optional<PartialDiagnostic> PartialDiag; - }; - - /// Creates a CUDADiagBuilder that emits the diagnostic if the current context - /// is "used as device code". - /// - /// - If CurContext is a __host__ function, does not emit any diagnostics. - /// - If CurContext is a __device__ or __global__ function, emits the - /// diagnostics immediately. - /// - If CurContext is a __host__ __device__ function and we are compiling for - /// the device, creates a diagnostic which is emitted if and when we realize - /// that the function will be codegen'ed. - /// - /// Example usage: - /// - /// // Variable-length arrays are not allowed in CUDA device code. - /// if (CUDADiagIfDeviceCode(Loc, diag::err_cuda_vla) << CurrentCUDATarget()) - /// return ExprError(); - /// // Otherwise, continue parsing as normal. - CUDADiagBuilder CUDADiagIfDeviceCode(SourceLocation Loc, unsigned DiagID); - - /// Creates a CUDADiagBuilder that emits the diagnostic if the current context - /// is "used as host code". - /// - /// Same as CUDADiagIfDeviceCode, with "host" and "device" switched. - CUDADiagBuilder CUDADiagIfHostCode(SourceLocation Loc, unsigned DiagID); - enum CUDAFunctionTarget { CFT_Device, CFT_Global, @@ -9600,31 +8747,14 @@ public: CFT_InvalidTarget }; - /// Determines whether the given function is a CUDA device/host/kernel/etc. - /// function. - /// - /// Use this rather than examining the function's attributes yourself -- you - /// will get it wrong. Returns CFT_Host if D is null. - CUDAFunctionTarget IdentifyCUDATarget(const FunctionDecl *D, - bool IgnoreImplicitHDAttr = false); - CUDAFunctionTarget IdentifyCUDATarget(const AttributeList *Attr); + CUDAFunctionTarget IdentifyCUDATarget(const FunctionDecl *D); - /// Gets the CUDA target for the current context. - CUDAFunctionTarget CurrentCUDATarget() { - return IdentifyCUDATarget(dyn_cast<FunctionDecl>(CurContext)); - } - - // CUDA function call preference. Must be ordered numerically from - // worst to best. enum CUDAFunctionPreference { CFP_Never, // Invalid caller/callee combination. - CFP_WrongSide, // Calls from host-device to host or device - // function that do not match current compilation - // mode. - CFP_HostDevice, // Any calls to host/device functions. - CFP_SameSide, // Calls from host-device to host or device - // function matching current compilation mode. - CFP_Native, // host-to-host or device-to-device calls. + CFP_LastResort, // Lowest priority. Only in effect if + // LangOpts.CUDADisableTargetCallChecks is true. + CFP_Fallback, // Low priority caller/callee combination + CFP_Best, // Preferred caller/callee combination }; /// Identifies relative preference of a given Caller/Callee @@ -9637,49 +8767,15 @@ public: CUDAFunctionPreference IdentifyCUDAPreference(const FunctionDecl *Caller, const FunctionDecl *Callee); - /// Determines whether Caller may invoke Callee, based on their CUDA - /// host/device attributes. Returns false if the call is not allowed. - /// - /// Note: Will return true for CFP_WrongSide calls. These may appear in - /// semantically correct CUDA programs, but only if they're never codegen'ed. - bool IsAllowedCUDACall(const FunctionDecl *Caller, - const FunctionDecl *Callee) { - return IdentifyCUDAPreference(Caller, Callee) != CFP_Never; - } - - /// May add implicit CUDAHostAttr and CUDADeviceAttr attributes to FD, - /// depending on FD and the current compilation settings. - void maybeAddCUDAHostDeviceAttrs(FunctionDecl *FD, - const LookupResult &Previous); - -public: - /// Check whether we're allowed to call Callee from the current context. - /// - /// - If the call is never allowed in a semantically-correct program - /// (CFP_Never), emits an error and returns false. - /// - /// - If the call is allowed in semantically-correct programs, but only if - /// it's never codegen'ed (CFP_WrongSide), creates a deferred diagnostic to - /// be emitted if and when the caller is codegen'ed, and returns true. - /// - /// Will only create deferred diagnostics for a given SourceLocation once, - /// so you can safely call this multiple times without generating duplicate - /// deferred errors. - /// - /// - Otherwise, returns true without emitting any diagnostics. - bool CheckCUDACall(SourceLocation Loc, FunctionDecl *Callee); - - /// Set __device__ or __host__ __device__ attributes on the given lambda - /// operator() method. - /// - /// CUDA lambdas declared inside __device__ or __global__ functions inherit - /// the __device__ attribute. Similarly, lambdas inside __host__ __device__ - /// functions become __host__ __device__ themselves. - void CUDASetLambdaAttrs(CXXMethodDecl *Method); + bool CheckCUDATarget(const FunctionDecl *Caller, const FunctionDecl *Callee); /// Finds a function in \p Matches with highest calling priority /// from \p Caller context and erases all functions with lower /// calling priority. + void EraseUnwantedCUDAMatches(const FunctionDecl *Caller, + SmallVectorImpl<FunctionDecl *> &Matches); + void EraseUnwantedCUDAMatches(const FunctionDecl *Caller, + SmallVectorImpl<DeclAccessPair> &Matches); void EraseUnwantedCUDAMatches( const FunctionDecl *Caller, SmallVectorImpl<std::pair<DeclAccessPair, FunctionDecl *>> &Matches); @@ -9701,18 +8797,6 @@ public: bool ConstRHS, bool Diagnose); - /// \return true if \p CD can be considered empty according to CUDA - /// (E.2.3.1 in CUDA 7.5 Programming guide). - bool isEmptyCudaConstructor(SourceLocation Loc, CXXConstructorDecl *CD); - bool isEmptyCudaDestructor(SourceLocation Loc, CXXDestructorDecl *CD); - - /// Check whether NewFD is a valid overload for CUDA. Emits - /// diagnostics and invalidates NewFD if not. - void checkCUDATargetOverload(FunctionDecl *NewFD, - const LookupResult &Previous); - /// Copies target attributes from the template TD to the function FD. - void inheritCUDATargetAttrs(FunctionDecl *FD, const FunctionTemplateDecl &TD); - /// \name Code completion //@{ /// \brief Describes the context in which code completion occurs. @@ -9772,12 +8856,11 @@ public: void CodeCompleteExpression(Scope *S, const CodeCompleteExpressionData &Data); void CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, - SourceLocation OpLoc, bool IsArrow, - bool IsBaseExprStatement); + SourceLocation OpLoc, + bool IsArrow); void CodeCompletePostfixExpression(Scope *S, ExprResult LHS); void CodeCompleteTag(Scope *S, unsigned TagSpec); void CodeCompleteTypeQualifiers(DeclSpec &DS); - void CodeCompleteBracketDeclarator(Scope *S); void CodeCompleteCase(Scope *S); void CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args); void CodeCompleteConstructor(Scope *S, QualType Type, SourceLocation Loc, @@ -9851,9 +8934,6 @@ public: bool AtParameterName, ParsedType ReturnType, ArrayRef<IdentifierInfo *> SelIdents); - void CodeCompleteObjCClassPropertyRefExpr(Scope *S, IdentifierInfo &ClassName, - SourceLocation ClassNameLoc, - bool IsBaseExprStatement); void CodeCompletePreprocessorDirective(bool InConditional); void CodeCompleteInPreprocessorConditionalExclusion(Scope *S); void CodeCompletePreprocessorMacroName(bool IsDefinition); @@ -9903,12 +8983,11 @@ private: SourceLocation Loc); void checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto, - const Expr *ThisArg, ArrayRef<const Expr *> Args, - bool IsMemberFunction, SourceLocation Loc, SourceRange Range, + ArrayRef<const Expr *> Args, bool IsMemberFunction, + SourceLocation Loc, SourceRange Range, VariadicCallType CallType); bool CheckObjCString(Expr *Arg); - ExprResult CheckOSLogFormatStringArg(Expr *Arg); ExprResult CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, CallExpr *TheCall); @@ -9921,7 +9000,6 @@ private: bool CheckAArch64BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); bool CheckMipsBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); bool CheckSystemZBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); - bool CheckX86BuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall); bool CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); bool CheckPPCBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); @@ -9931,7 +9009,6 @@ private: bool SemaBuiltinVAStartARM(CallExpr *Call); bool SemaBuiltinUnorderedCompare(CallExpr *TheCall); bool SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs); - bool SemaBuiltinOSLogFormat(CallExpr *TheCall); public: // Used by C++ template instantiation. @@ -9942,7 +9019,6 @@ public: private: bool SemaBuiltinPrefetch(CallExpr *TheCall); - bool SemaBuiltinAllocaWithAlign(CallExpr *TheCall); bool SemaBuiltinAssume(CallExpr *TheCall); bool SemaBuiltinAssumeAligned(CallExpr *TheCall); bool SemaBuiltinLongjmp(CallExpr *TheCall); @@ -9955,8 +9031,6 @@ private: llvm::APSInt &Result); bool SemaBuiltinConstantArgRange(CallExpr *TheCall, int ArgNum, int Low, int High); - bool SemaBuiltinConstantArgMultiple(CallExpr *TheCall, int ArgNum, - unsigned Multiple); bool SemaBuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall, int ArgNum, unsigned ExpectedFieldNum, bool AllowName); @@ -9970,13 +9044,19 @@ public: FST_Kprintf, FST_FreeBSDKPrintf, FST_OSTrace, - FST_OSLog, FST_Unknown }; static FormatStringType GetFormatStringType(const FormatAttr *Format); + void CheckFormatString(const StringLiteral *FExpr, const Expr *OrigFormatExpr, + ArrayRef<const Expr *> Args, bool HasVAListArg, + unsigned format_idx, unsigned firstDataArg, + FormatStringType Type, bool inFunctionCall, + VariadicCallType CallType, + llvm::SmallBitVector &CheckedVarArgs); + bool FormatStringHasSArg(const StringLiteral *FExpr); - + static bool GetFormatNSStringIdx(const FormatAttr *Format, unsigned &Idx); private: @@ -9994,9 +9074,8 @@ private: llvm::SmallBitVector &CheckedVarArgs); void CheckAbsoluteValueFunction(const CallExpr *Call, - const FunctionDecl *FDecl); - - void CheckMaxUnsignedZero(const CallExpr *Call, const FunctionDecl *FDecl); + const FunctionDecl *FDecl, + IdentifierInfo *FnInfo); void CheckMemaccessArguments(const CallExpr *Call, unsigned BId, @@ -10075,10 +9154,6 @@ private: void CheckArgumentWithTypeTag(const ArgumentWithTypeTagAttr *Attr, const Expr * const *ExprArgs); - /// \brief Check if we are taking the address of a packed field - /// as this may be a problem if the pointer value is dereferenced. - void CheckAddressOfPackedMember(Expr *rhs); - /// \brief The parser's current scope. /// /// The parser maintains this state here. @@ -10134,17 +9209,8 @@ public: return OriginalLexicalContext ? OriginalLexicalContext : CurContext; } - /// \brief The diagnostic we should emit for \c D, or \c AR_Available. - /// - /// \param D The declaration to check. Note that this may be altered to point - /// to another declaration that \c D gets it's availability from. i.e., we - /// walk the list of typedefs to find an availability attribute. - /// - /// \param Message If non-null, this will be populated with the message from - /// the availability attribute that is selected. - AvailabilityResult ShouldDiagnoseAvailabilityOfDecl(NamedDecl *&D, - std::string *Message); - + AvailabilityResult getCurContextAvailability() const; + const DeclContext *getCurObjCLexicalContext() const { const DeclContext *DC = getCurLexicalContext(); // A category implicitly has the attribute of the interface. @@ -10166,100 +9232,33 @@ public: // Emitting members of dllexported classes is delayed until the class // (including field initializers) is fully parsed. SmallVector<CXXRecordDecl*, 4> DelayedDllExportClasses; - -private: - /// \brief Helper class that collects misaligned member designations and - /// their location info for delayed diagnostics. - struct MisalignedMember { - Expr *E; - RecordDecl *RD; - ValueDecl *MD; - CharUnits Alignment; - - MisalignedMember() : E(), RD(), MD(), Alignment() {} - MisalignedMember(Expr *E, RecordDecl *RD, ValueDecl *MD, - CharUnits Alignment) - : E(E), RD(RD), MD(MD), Alignment(Alignment) {} - explicit MisalignedMember(Expr *E) - : MisalignedMember(E, nullptr, nullptr, CharUnits()) {} - - bool operator==(const MisalignedMember &m) { return this->E == m.E; } - }; - /// \brief Small set of gathered accesses to potentially misaligned members - /// due to the packed attribute. - SmallVector<MisalignedMember, 4> MisalignedMembers; - - /// \brief Adds an expression to the set of gathered misaligned members. - void AddPotentialMisalignedMembers(Expr *E, RecordDecl *RD, ValueDecl *MD, - CharUnits Alignment); - -public: - /// \brief Diagnoses the current set of gathered accesses. This typically - /// happens at full expression level. The set is cleared after emitting the - /// diagnostics. - void DiagnoseMisalignedMembers(); - - /// \brief This function checks if the expression is in the sef of potentially - /// misaligned members and it is converted to some pointer type T with lower - /// or equal alignment requirements. If so it removes it. This is used when - /// we do not want to diagnose such misaligned access (e.g. in conversions to - /// void*). - void DiscardMisalignedMemberAddress(const Type *T, Expr *E); - - /// \brief This function calls Action when it determines that E designates a - /// misaligned member due to the packed attribute. This is used to emit - /// local diagnostics like in reference binding. - void RefersToMemberWithReducedAlignment( - Expr *E, - llvm::function_ref<void(Expr *, RecordDecl *, FieldDecl *, CharUnits)> - Action); }; /// \brief RAII object that enters a new expression evaluation context. class EnterExpressionEvaluationContext { Sema &Actions; - bool Entered = true; public: EnterExpressionEvaluationContext(Sema &Actions, Sema::ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl = nullptr, - bool IsDecltype = false, - bool ShouldEnter = true) - : Actions(Actions), Entered(ShouldEnter) { - if (Entered) - Actions.PushExpressionEvaluationContext(NewContext, LambdaContextDecl, - IsDecltype); + bool IsDecltype = false) + : Actions(Actions) { + Actions.PushExpressionEvaluationContext(NewContext, LambdaContextDecl, + IsDecltype); } EnterExpressionEvaluationContext(Sema &Actions, Sema::ExpressionEvaluationContext NewContext, Sema::ReuseLambdaContextDecl_t, bool IsDecltype = false) : Actions(Actions) { - Actions.PushExpressionEvaluationContext(NewContext, + Actions.PushExpressionEvaluationContext(NewContext, Sema::ReuseLambdaContextDecl, IsDecltype); } - enum InitListTag { InitList }; - EnterExpressionEvaluationContext(Sema &Actions, InitListTag, - bool ShouldEnter = true) - : Actions(Actions), Entered(false) { - // In C++11 onwards, narrowing checks are performed on the contents of - // braced-init-lists, even when they occur within unevaluated operands. - // Therefore we still need to instantiate constexpr functions used in such - // a context. - if (ShouldEnter && Actions.isUnevaluatedContext() && - Actions.getLangOpts().CPlusPlus11) { - Actions.PushExpressionEvaluationContext(Sema::UnevaluatedList, nullptr, - false); - Entered = true; - } - } - ~EnterExpressionEvaluationContext() { - if (Entered) - Actions.PopExpressionEvaluationContext(); + Actions.PopExpressionEvaluationContext(); } }; @@ -10277,31 +9276,4 @@ struct LateParsedTemplate { } // end namespace clang -namespace llvm { -// Hash a FunctionDeclAndLoc by looking at both its FunctionDecl and its -// SourceLocation. -template <> struct DenseMapInfo<clang::Sema::FunctionDeclAndLoc> { - using FunctionDeclAndLoc = clang::Sema::FunctionDeclAndLoc; - using FDBaseInfo = DenseMapInfo<clang::CanonicalDeclPtr<clang::FunctionDecl>>; - - static FunctionDeclAndLoc getEmptyKey() { - return {FDBaseInfo::getEmptyKey(), clang::SourceLocation()}; - } - - static FunctionDeclAndLoc getTombstoneKey() { - return {FDBaseInfo::getTombstoneKey(), clang::SourceLocation()}; - } - - static unsigned getHashValue(const FunctionDeclAndLoc &FDL) { - return hash_combine(FDBaseInfo::getHashValue(FDL.FD), - FDL.Loc.getRawEncoding()); - } - - static bool isEqual(const FunctionDeclAndLoc &LHS, - const FunctionDeclAndLoc &RHS) { - return LHS.FD == RHS.FD && LHS.Loc == RHS.Loc; - } -}; -} // namespace llvm - #endif diff --git a/gnu/llvm/tools/clang/lib/Sema/SemaChecking.cpp b/gnu/llvm/tools/clang/lib/Sema/SemaChecking.cpp index 3aedb2a8c9b..6c2834b750a 100644 --- a/gnu/llvm/tools/clang/lib/Sema/SemaChecking.cpp +++ b/gnu/llvm/tools/clang/lib/Sema/SemaChecking.cpp @@ -12,6 +12,7 @@ // //===----------------------------------------------------------------------===// +#include "clang/Sema/SemaInternal.h" #include "clang/AST/ASTContext.h" #include "clang/AST/CharUnits.h" #include "clang/AST/DeclCXX.h" @@ -32,15 +33,12 @@ #include "clang/Sema/Lookup.h" #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/Sema.h" -#include "clang/Sema/SemaInternal.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallBitVector.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/ConvertUTF.h" -#include "llvm/Support/Format.h" -#include "llvm/Support/Locale.h" #include "llvm/Support/raw_ostream.h" - +#include <limits> using namespace clang; using namespace sema; @@ -260,473 +258,6 @@ static bool SemaBuiltinSEHScopeCheck(Sema &SemaRef, CallExpr *TheCall, return false; } -static inline bool isBlockPointer(Expr *Arg) { - return Arg->getType()->isBlockPointerType(); -} - -/// OpenCL C v2.0, s6.13.17.2 - Checks that the block parameters are all local -/// void*, which is a requirement of device side enqueue. -static bool checkOpenCLBlockArgs(Sema &S, Expr *BlockArg) { - const BlockPointerType *BPT = - cast<BlockPointerType>(BlockArg->getType().getCanonicalType()); - ArrayRef<QualType> Params = - BPT->getPointeeType()->getAs<FunctionProtoType>()->getParamTypes(); - unsigned ArgCounter = 0; - bool IllegalParams = false; - // Iterate through the block parameters until either one is found that is not - // a local void*, or the block is valid. - for (ArrayRef<QualType>::iterator I = Params.begin(), E = Params.end(); - I != E; ++I, ++ArgCounter) { - if (!(*I)->isPointerType() || !(*I)->getPointeeType()->isVoidType() || - (*I)->getPointeeType().getQualifiers().getAddressSpace() != - LangAS::opencl_local) { - // Get the location of the error. If a block literal has been passed - // (BlockExpr) then we can point straight to the offending argument, - // else we just point to the variable reference. - SourceLocation ErrorLoc; - if (isa<BlockExpr>(BlockArg)) { - BlockDecl *BD = cast<BlockExpr>(BlockArg)->getBlockDecl(); - ErrorLoc = BD->getParamDecl(ArgCounter)->getLocStart(); - } else if (isa<DeclRefExpr>(BlockArg)) { - ErrorLoc = cast<DeclRefExpr>(BlockArg)->getLocStart(); - } - S.Diag(ErrorLoc, - diag::err_opencl_enqueue_kernel_blocks_non_local_void_args); - IllegalParams = true; - } - } - - return IllegalParams; -} - -/// OpenCL C v2.0, s6.13.17.6 - Check the argument to the -/// get_kernel_work_group_size -/// and get_kernel_preferred_work_group_size_multiple builtin functions. -static bool SemaOpenCLBuiltinKernelWorkGroupSize(Sema &S, CallExpr *TheCall) { - if (checkArgCount(S, TheCall, 1)) - return true; - - Expr *BlockArg = TheCall->getArg(0); - if (!isBlockPointer(BlockArg)) { - S.Diag(BlockArg->getLocStart(), - diag::err_opencl_enqueue_kernel_expected_type) << "block"; - return true; - } - return checkOpenCLBlockArgs(S, BlockArg); -} - -/// Diagnose integer type and any valid implicit convertion to it. -static bool checkOpenCLEnqueueIntType(Sema &S, Expr *E, - const QualType &IntType); - -static bool checkOpenCLEnqueueLocalSizeArgs(Sema &S, CallExpr *TheCall, - unsigned Start, unsigned End) { - bool IllegalParams = false; - for (unsigned I = Start; I <= End; ++I) - IllegalParams |= checkOpenCLEnqueueIntType(S, TheCall->getArg(I), - S.Context.getSizeType()); - return IllegalParams; -} - -/// OpenCL v2.0, s6.13.17.1 - Check that sizes are provided for all -/// 'local void*' parameter of passed block. -static bool checkOpenCLEnqueueVariadicArgs(Sema &S, CallExpr *TheCall, - Expr *BlockArg, - unsigned NumNonVarArgs) { - const BlockPointerType *BPT = - cast<BlockPointerType>(BlockArg->getType().getCanonicalType()); - unsigned NumBlockParams = - BPT->getPointeeType()->getAs<FunctionProtoType>()->getNumParams(); - unsigned TotalNumArgs = TheCall->getNumArgs(); - - // For each argument passed to the block, a corresponding uint needs to - // be passed to describe the size of the local memory. - if (TotalNumArgs != NumBlockParams + NumNonVarArgs) { - S.Diag(TheCall->getLocStart(), - diag::err_opencl_enqueue_kernel_local_size_args); - return true; - } - - // Check that the sizes of the local memory are specified by integers. - return checkOpenCLEnqueueLocalSizeArgs(S, TheCall, NumNonVarArgs, - TotalNumArgs - 1); -} - -/// OpenCL C v2.0, s6.13.17 - Enqueue kernel function contains four different -/// overload formats specified in Table 6.13.17.1. -/// int enqueue_kernel(queue_t queue, -/// kernel_enqueue_flags_t flags, -/// const ndrange_t ndrange, -/// void (^block)(void)) -/// int enqueue_kernel(queue_t queue, -/// kernel_enqueue_flags_t flags, -/// const ndrange_t ndrange, -/// uint num_events_in_wait_list, -/// clk_event_t *event_wait_list, -/// clk_event_t *event_ret, -/// void (^block)(void)) -/// int enqueue_kernel(queue_t queue, -/// kernel_enqueue_flags_t flags, -/// const ndrange_t ndrange, -/// void (^block)(local void*, ...), -/// uint size0, ...) -/// int enqueue_kernel(queue_t queue, -/// kernel_enqueue_flags_t flags, -/// const ndrange_t ndrange, -/// uint num_events_in_wait_list, -/// clk_event_t *event_wait_list, -/// clk_event_t *event_ret, -/// void (^block)(local void*, ...), -/// uint size0, ...) -static bool SemaOpenCLBuiltinEnqueueKernel(Sema &S, CallExpr *TheCall) { - unsigned NumArgs = TheCall->getNumArgs(); - - if (NumArgs < 4) { - S.Diag(TheCall->getLocStart(), diag::err_typecheck_call_too_few_args); - return true; - } - - Expr *Arg0 = TheCall->getArg(0); - Expr *Arg1 = TheCall->getArg(1); - Expr *Arg2 = TheCall->getArg(2); - Expr *Arg3 = TheCall->getArg(3); - - // First argument always needs to be a queue_t type. - if (!Arg0->getType()->isQueueT()) { - S.Diag(TheCall->getArg(0)->getLocStart(), - diag::err_opencl_enqueue_kernel_expected_type) - << S.Context.OCLQueueTy; - return true; - } - - // Second argument always needs to be a kernel_enqueue_flags_t enum value. - if (!Arg1->getType()->isIntegerType()) { - S.Diag(TheCall->getArg(1)->getLocStart(), - diag::err_opencl_enqueue_kernel_expected_type) - << "'kernel_enqueue_flags_t' (i.e. uint)"; - return true; - } - - // Third argument is always an ndrange_t type. - if (!Arg2->getType()->isNDRangeT()) { - S.Diag(TheCall->getArg(2)->getLocStart(), - diag::err_opencl_enqueue_kernel_expected_type) - << S.Context.OCLNDRangeTy; - return true; - } - - // With four arguments, there is only one form that the function could be - // called in: no events and no variable arguments. - if (NumArgs == 4) { - // check that the last argument is the right block type. - if (!isBlockPointer(Arg3)) { - S.Diag(Arg3->getLocStart(), diag::err_opencl_enqueue_kernel_expected_type) - << "block"; - return true; - } - // we have a block type, check the prototype - const BlockPointerType *BPT = - cast<BlockPointerType>(Arg3->getType().getCanonicalType()); - if (BPT->getPointeeType()->getAs<FunctionProtoType>()->getNumParams() > 0) { - S.Diag(Arg3->getLocStart(), - diag::err_opencl_enqueue_kernel_blocks_no_args); - return true; - } - return false; - } - // we can have block + varargs. - if (isBlockPointer(Arg3)) - return (checkOpenCLBlockArgs(S, Arg3) || - checkOpenCLEnqueueVariadicArgs(S, TheCall, Arg3, 4)); - // last two cases with either exactly 7 args or 7 args and varargs. - if (NumArgs >= 7) { - // check common block argument. - Expr *Arg6 = TheCall->getArg(6); - if (!isBlockPointer(Arg6)) { - S.Diag(Arg6->getLocStart(), diag::err_opencl_enqueue_kernel_expected_type) - << "block"; - return true; - } - if (checkOpenCLBlockArgs(S, Arg6)) - return true; - - // Forth argument has to be any integer type. - if (!Arg3->getType()->isIntegerType()) { - S.Diag(TheCall->getArg(3)->getLocStart(), - diag::err_opencl_enqueue_kernel_expected_type) - << "integer"; - return true; - } - // check remaining common arguments. - Expr *Arg4 = TheCall->getArg(4); - Expr *Arg5 = TheCall->getArg(5); - - // Fifth argument is always passed as a pointer to clk_event_t. - if (!Arg4->isNullPointerConstant(S.Context, - Expr::NPC_ValueDependentIsNotNull) && - !Arg4->getType()->getPointeeOrArrayElementType()->isClkEventT()) { - S.Diag(TheCall->getArg(4)->getLocStart(), - diag::err_opencl_enqueue_kernel_expected_type) - << S.Context.getPointerType(S.Context.OCLClkEventTy); - return true; - } - - // Sixth argument is always passed as a pointer to clk_event_t. - if (!Arg5->isNullPointerConstant(S.Context, - Expr::NPC_ValueDependentIsNotNull) && - !(Arg5->getType()->isPointerType() && - Arg5->getType()->getPointeeType()->isClkEventT())) { - S.Diag(TheCall->getArg(5)->getLocStart(), - diag::err_opencl_enqueue_kernel_expected_type) - << S.Context.getPointerType(S.Context.OCLClkEventTy); - return true; - } - - if (NumArgs == 7) - return false; - - return checkOpenCLEnqueueVariadicArgs(S, TheCall, Arg6, 7); - } - - // None of the specific case has been detected, give generic error - S.Diag(TheCall->getLocStart(), - diag::err_opencl_enqueue_kernel_incorrect_args); - return true; -} - -/// Returns OpenCL access qual. -static OpenCLAccessAttr *getOpenCLArgAccess(const Decl *D) { - return D->getAttr<OpenCLAccessAttr>(); -} - -/// Returns true if pipe element type is different from the pointer. -static bool checkOpenCLPipeArg(Sema &S, CallExpr *Call) { - const Expr *Arg0 = Call->getArg(0); - // First argument type should always be pipe. - if (!Arg0->getType()->isPipeType()) { - S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_first_arg) - << Call->getDirectCallee() << Arg0->getSourceRange(); - return true; - } - OpenCLAccessAttr *AccessQual = - getOpenCLArgAccess(cast<DeclRefExpr>(Arg0)->getDecl()); - // Validates the access qualifier is compatible with the call. - // OpenCL v2.0 s6.13.16 - The access qualifiers for pipe should only be - // read_only and write_only, and assumed to be read_only if no qualifier is - // specified. - switch (Call->getDirectCallee()->getBuiltinID()) { - case Builtin::BIread_pipe: - case Builtin::BIreserve_read_pipe: - case Builtin::BIcommit_read_pipe: - case Builtin::BIwork_group_reserve_read_pipe: - case Builtin::BIsub_group_reserve_read_pipe: - case Builtin::BIwork_group_commit_read_pipe: - case Builtin::BIsub_group_commit_read_pipe: - if (!(!AccessQual || AccessQual->isReadOnly())) { - S.Diag(Arg0->getLocStart(), - diag::err_opencl_builtin_pipe_invalid_access_modifier) - << "read_only" << Arg0->getSourceRange(); - return true; - } - break; - case Builtin::BIwrite_pipe: - case Builtin::BIreserve_write_pipe: - case Builtin::BIcommit_write_pipe: - case Builtin::BIwork_group_reserve_write_pipe: - case Builtin::BIsub_group_reserve_write_pipe: - case Builtin::BIwork_group_commit_write_pipe: - case Builtin::BIsub_group_commit_write_pipe: - if (!(AccessQual && AccessQual->isWriteOnly())) { - S.Diag(Arg0->getLocStart(), - diag::err_opencl_builtin_pipe_invalid_access_modifier) - << "write_only" << Arg0->getSourceRange(); - return true; - } - break; - default: - break; - } - return false; -} - -/// Returns true if pipe element type is different from the pointer. -static bool checkOpenCLPipePacketType(Sema &S, CallExpr *Call, unsigned Idx) { - const Expr *Arg0 = Call->getArg(0); - const Expr *ArgIdx = Call->getArg(Idx); - const PipeType *PipeTy = cast<PipeType>(Arg0->getType()); - const QualType EltTy = PipeTy->getElementType(); - const PointerType *ArgTy = ArgIdx->getType()->getAs<PointerType>(); - // The Idx argument should be a pointer and the type of the pointer and - // the type of pipe element should also be the same. - if (!ArgTy || - !S.Context.hasSameType( - EltTy, ArgTy->getPointeeType()->getCanonicalTypeInternal())) { - S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_invalid_arg) - << Call->getDirectCallee() << S.Context.getPointerType(EltTy) - << ArgIdx->getType() << ArgIdx->getSourceRange(); - return true; - } - return false; -} - -// \brief Performs semantic analysis for the read/write_pipe call. -// \param S Reference to the semantic analyzer. -// \param Call A pointer to the builtin call. -// \return True if a semantic error has been found, false otherwise. -static bool SemaBuiltinRWPipe(Sema &S, CallExpr *Call) { - // OpenCL v2.0 s6.13.16.2 - The built-in read/write - // functions have two forms. - switch (Call->getNumArgs()) { - case 2: { - if (checkOpenCLPipeArg(S, Call)) - return true; - // The call with 2 arguments should be - // read/write_pipe(pipe T, T*). - // Check packet type T. - if (checkOpenCLPipePacketType(S, Call, 1)) - return true; - } break; - - case 4: { - if (checkOpenCLPipeArg(S, Call)) - return true; - // The call with 4 arguments should be - // read/write_pipe(pipe T, reserve_id_t, uint, T*). - // Check reserve_id_t. - if (!Call->getArg(1)->getType()->isReserveIDT()) { - S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_invalid_arg) - << Call->getDirectCallee() << S.Context.OCLReserveIDTy - << Call->getArg(1)->getType() << Call->getArg(1)->getSourceRange(); - return true; - } - - // Check the index. - const Expr *Arg2 = Call->getArg(2); - if (!Arg2->getType()->isIntegerType() && - !Arg2->getType()->isUnsignedIntegerType()) { - S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_invalid_arg) - << Call->getDirectCallee() << S.Context.UnsignedIntTy - << Arg2->getType() << Arg2->getSourceRange(); - return true; - } - - // Check packet type T. - if (checkOpenCLPipePacketType(S, Call, 3)) - return true; - } break; - default: - S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_arg_num) - << Call->getDirectCallee() << Call->getSourceRange(); - return true; - } - - return false; -} - -// \brief Performs a semantic analysis on the {work_group_/sub_group_ -// /_}reserve_{read/write}_pipe -// \param S Reference to the semantic analyzer. -// \param Call The call to the builtin function to be analyzed. -// \return True if a semantic error was found, false otherwise. -static bool SemaBuiltinReserveRWPipe(Sema &S, CallExpr *Call) { - if (checkArgCount(S, Call, 2)) - return true; - - if (checkOpenCLPipeArg(S, Call)) - return true; - - // Check the reserve size. - if (!Call->getArg(1)->getType()->isIntegerType() && - !Call->getArg(1)->getType()->isUnsignedIntegerType()) { - S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_invalid_arg) - << Call->getDirectCallee() << S.Context.UnsignedIntTy - << Call->getArg(1)->getType() << Call->getArg(1)->getSourceRange(); - return true; - } - - return false; -} - -// \brief Performs a semantic analysis on {work_group_/sub_group_ -// /_}commit_{read/write}_pipe -// \param S Reference to the semantic analyzer. -// \param Call The call to the builtin function to be analyzed. -// \return True if a semantic error was found, false otherwise. -static bool SemaBuiltinCommitRWPipe(Sema &S, CallExpr *Call) { - if (checkArgCount(S, Call, 2)) - return true; - - if (checkOpenCLPipeArg(S, Call)) - return true; - - // Check reserve_id_t. - if (!Call->getArg(1)->getType()->isReserveIDT()) { - S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_invalid_arg) - << Call->getDirectCallee() << S.Context.OCLReserveIDTy - << Call->getArg(1)->getType() << Call->getArg(1)->getSourceRange(); - return true; - } - - return false; -} - -// \brief Performs a semantic analysis on the call to built-in Pipe -// Query Functions. -// \param S Reference to the semantic analyzer. -// \param Call The call to the builtin function to be analyzed. -// \return True if a semantic error was found, false otherwise. -static bool SemaBuiltinPipePackets(Sema &S, CallExpr *Call) { - if (checkArgCount(S, Call, 1)) - return true; - - if (!Call->getArg(0)->getType()->isPipeType()) { - S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_first_arg) - << Call->getDirectCallee() << Call->getArg(0)->getSourceRange(); - return true; - } - - return false; -} -// \brief OpenCL v2.0 s6.13.9 - Address space qualifier functions. -// \brief Performs semantic analysis for the to_global/local/private call. -// \param S Reference to the semantic analyzer. -// \param BuiltinID ID of the builtin function. -// \param Call A pointer to the builtin call. -// \return True if a semantic error has been found, false otherwise. -static bool SemaOpenCLBuiltinToAddr(Sema &S, unsigned BuiltinID, - CallExpr *Call) { - if (Call->getNumArgs() != 1) { - S.Diag(Call->getLocStart(), diag::err_opencl_builtin_to_addr_arg_num) - << Call->getDirectCallee() << Call->getSourceRange(); - return true; - } - - auto RT = Call->getArg(0)->getType(); - if (!RT->isPointerType() || RT->getPointeeType() - .getAddressSpace() == LangAS::opencl_constant) { - S.Diag(Call->getLocStart(), diag::err_opencl_builtin_to_addr_invalid_arg) - << Call->getArg(0) << Call->getDirectCallee() << Call->getSourceRange(); - return true; - } - - RT = RT->getPointeeType(); - auto Qual = RT.getQualifiers(); - switch (BuiltinID) { - case Builtin::BIto_global: - Qual.setAddressSpace(LangAS::opencl_global); - break; - case Builtin::BIto_local: - Qual.setAddressSpace(LangAS::opencl_local); - break; - default: - Qual.removeAddressSpace(); - } - Call->setType(S.Context.getPointerType(S.Context.getQualifiedType( - RT.getUnqualifiedType(), Qual))); - - return false; -} - ExprResult Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, CallExpr *TheCall) { @@ -805,10 +336,6 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, if (SemaBuiltinPrefetch(TheCall)) return ExprError(); break; - case Builtin::BI__builtin_alloca_with_align: - if (SemaBuiltinAllocaWithAlign(TheCall)) - return ExprError(); - break; case Builtin::BI__assume: case Builtin::BI__builtin_assume: if (SemaBuiltinAssume(TheCall)) @@ -1003,22 +530,27 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, case Builtin::BI__builtin___vsnprintf_chk: SemaBuiltinMemChkCall(*this, FDecl, TheCall, 1, 3); break; + case Builtin::BI__builtin_call_with_static_chain: if (SemaBuiltinCallWithStaticChain(*this, TheCall)) return ExprError(); break; + case Builtin::BI__exception_code: - case Builtin::BI_exception_code: + case Builtin::BI_exception_code: { if (SemaBuiltinSEHScopeCheck(*this, TheCall, Scope::SEHExceptScope, diag::err_seh___except_block)) return ExprError(); break; + } case Builtin::BI__exception_info: - case Builtin::BI_exception_info: + case Builtin::BI_exception_info: { if (SemaBuiltinSEHScopeCheck(*this, TheCall, Scope::SEHFilterScope, diag::err_seh___except_filter)) return ExprError(); break; + } + case Builtin::BI__GetExceptionInfo: if (checkArgCount(*this, TheCall, 1)) return ExprError(); @@ -1031,65 +563,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, TheCall->setType(Context.VoidPtrTy); break; - // OpenCL v2.0, s6.13.16 - Pipe functions - case Builtin::BIread_pipe: - case Builtin::BIwrite_pipe: - // Since those two functions are declared with var args, we need a semantic - // check for the argument. - if (SemaBuiltinRWPipe(*this, TheCall)) - return ExprError(); - TheCall->setType(Context.IntTy); - break; - case Builtin::BIreserve_read_pipe: - case Builtin::BIreserve_write_pipe: - case Builtin::BIwork_group_reserve_read_pipe: - case Builtin::BIwork_group_reserve_write_pipe: - case Builtin::BIsub_group_reserve_read_pipe: - case Builtin::BIsub_group_reserve_write_pipe: - if (SemaBuiltinReserveRWPipe(*this, TheCall)) - return ExprError(); - // Since return type of reserve_read/write_pipe built-in function is - // reserve_id_t, which is not defined in the builtin def file , we used int - // as return type and need to override the return type of these functions. - TheCall->setType(Context.OCLReserveIDTy); - break; - case Builtin::BIcommit_read_pipe: - case Builtin::BIcommit_write_pipe: - case Builtin::BIwork_group_commit_read_pipe: - case Builtin::BIwork_group_commit_write_pipe: - case Builtin::BIsub_group_commit_read_pipe: - case Builtin::BIsub_group_commit_write_pipe: - if (SemaBuiltinCommitRWPipe(*this, TheCall)) - return ExprError(); - break; - case Builtin::BIget_pipe_num_packets: - case Builtin::BIget_pipe_max_packets: - if (SemaBuiltinPipePackets(*this, TheCall)) - return ExprError(); - TheCall->setType(Context.UnsignedIntTy); - break; - case Builtin::BIto_global: - case Builtin::BIto_local: - case Builtin::BIto_private: - if (SemaOpenCLBuiltinToAddr(*this, BuiltinID, TheCall)) - return ExprError(); - break; - // OpenCL v2.0, s6.13.17 - Enqueue kernel functions. - case Builtin::BIenqueue_kernel: - if (SemaOpenCLBuiltinEnqueueKernel(*this, TheCall)) - return ExprError(); - break; - case Builtin::BIget_kernel_work_group_size: - case Builtin::BIget_kernel_preferred_work_group_size_multiple: - if (SemaOpenCLBuiltinKernelWorkGroupSize(*this, TheCall)) - return ExprError(); - break; - case Builtin::BI__builtin_os_log_format: - case Builtin::BI__builtin_os_log_format_buffer_size: - if (SemaBuiltinOSLogFormat(TheCall)) { - return ExprError(); - } - break; + } // Since the target specific builtins for each arch overlap, only check those @@ -1242,8 +716,7 @@ bool Sema::CheckNeonBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { QualType RHSTy = RHS.get()->getType(); llvm::Triple::ArchType Arch = Context.getTargetInfo().getTriple().getArch(); - bool IsPolyUnsigned = Arch == llvm::Triple::aarch64 || - Arch == llvm::Triple::aarch64_be; + bool IsPolyUnsigned = Arch == llvm::Triple::aarch64; bool IsInt64Long = Context.getTargetInfo().getInt64Type() == TargetInfo::SignedLong; QualType EltTy = @@ -1370,6 +843,7 @@ bool Sema::CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall, return true; } + if (IsLdrex) { TheCall->setType(ValType); return false; @@ -1457,7 +931,7 @@ bool Sema::CheckAArch64BuiltinFunctionCall(unsigned BuiltinID, if (BuiltinID == AArch64::BI__builtin_arm_rsr64 || BuiltinID == AArch64::BI__builtin_arm_wsr64) - return SemaBuiltinARMSpecialReg(BuiltinID, TheCall, 0, 5, true); + return SemaBuiltinARMSpecialReg(BuiltinID, TheCall, 0, 5, false); if (BuiltinID == AArch64::BI__builtin_arm_rsr || BuiltinID == AArch64::BI__builtin_arm_rsrp || @@ -1481,17 +955,8 @@ bool Sema::CheckAArch64BuiltinFunctionCall(unsigned BuiltinID, return SemaBuiltinConstantArgRange(TheCall, i, l, u + l); } -// CheckMipsBuiltinFunctionCall - Checks the constant value passed to the -// intrinsic is correct. The switch statement is ordered by DSP, MSA. The -// ordering for DSP is unspecified. MSA is ordered by the data format used -// by the underlying instruction i.e., df/m, df/n and then by size. -// -// FIXME: The size tests here should instead be tablegen'd along with the -// definitions from include/clang/Basic/BuiltinsMips.def. -// FIXME: GCC is strict on signedness for some of these intrinsics, we should -// be too. bool Sema::CheckMipsBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { - unsigned i = 0, l = 0, u = 0, m = 0; + unsigned i = 0, l = 0, u = 0; switch (BuiltinID) { default: return false; case Mips::BI__builtin_mips_wrdsp: i = 1; l = 0; u = 63; break; @@ -1501,168 +966,9 @@ bool Sema::CheckMipsBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { case Mips::BI__builtin_mips_precr_sra_ph_w: i = 2; l = 0; u = 31; break; case Mips::BI__builtin_mips_precr_sra_r_ph_w: i = 2; l = 0; u = 31; break; case Mips::BI__builtin_mips_prepend: i = 2; l = 0; u = 31; break; - // MSA instrinsics. Instructions (which the intrinsics maps to) which use the - // df/m field. - // These intrinsics take an unsigned 3 bit immediate. - case Mips::BI__builtin_msa_bclri_b: - case Mips::BI__builtin_msa_bnegi_b: - case Mips::BI__builtin_msa_bseti_b: - case Mips::BI__builtin_msa_sat_s_b: - case Mips::BI__builtin_msa_sat_u_b: - case Mips::BI__builtin_msa_slli_b: - case Mips::BI__builtin_msa_srai_b: - case Mips::BI__builtin_msa_srari_b: - case Mips::BI__builtin_msa_srli_b: - case Mips::BI__builtin_msa_srlri_b: i = 1; l = 0; u = 7; break; - case Mips::BI__builtin_msa_binsli_b: - case Mips::BI__builtin_msa_binsri_b: i = 2; l = 0; u = 7; break; - // These intrinsics take an unsigned 4 bit immediate. - case Mips::BI__builtin_msa_bclri_h: - case Mips::BI__builtin_msa_bnegi_h: - case Mips::BI__builtin_msa_bseti_h: - case Mips::BI__builtin_msa_sat_s_h: - case Mips::BI__builtin_msa_sat_u_h: - case Mips::BI__builtin_msa_slli_h: - case Mips::BI__builtin_msa_srai_h: - case Mips::BI__builtin_msa_srari_h: - case Mips::BI__builtin_msa_srli_h: - case Mips::BI__builtin_msa_srlri_h: i = 1; l = 0; u = 15; break; - case Mips::BI__builtin_msa_binsli_h: - case Mips::BI__builtin_msa_binsri_h: i = 2; l = 0; u = 15; break; - // These intrinsics take an unsigned 5 bit immedate. - // The first block of intrinsics actually have an unsigned 5 bit field, - // not a df/n field. - case Mips::BI__builtin_msa_clei_u_b: - case Mips::BI__builtin_msa_clei_u_h: - case Mips::BI__builtin_msa_clei_u_w: - case Mips::BI__builtin_msa_clei_u_d: - case Mips::BI__builtin_msa_clti_u_b: - case Mips::BI__builtin_msa_clti_u_h: - case Mips::BI__builtin_msa_clti_u_w: - case Mips::BI__builtin_msa_clti_u_d: - case Mips::BI__builtin_msa_maxi_u_b: - case Mips::BI__builtin_msa_maxi_u_h: - case Mips::BI__builtin_msa_maxi_u_w: - case Mips::BI__builtin_msa_maxi_u_d: - case Mips::BI__builtin_msa_mini_u_b: - case Mips::BI__builtin_msa_mini_u_h: - case Mips::BI__builtin_msa_mini_u_w: - case Mips::BI__builtin_msa_mini_u_d: - case Mips::BI__builtin_msa_addvi_b: - case Mips::BI__builtin_msa_addvi_h: - case Mips::BI__builtin_msa_addvi_w: - case Mips::BI__builtin_msa_addvi_d: - case Mips::BI__builtin_msa_bclri_w: - case Mips::BI__builtin_msa_bnegi_w: - case Mips::BI__builtin_msa_bseti_w: - case Mips::BI__builtin_msa_sat_s_w: - case Mips::BI__builtin_msa_sat_u_w: - case Mips::BI__builtin_msa_slli_w: - case Mips::BI__builtin_msa_srai_w: - case Mips::BI__builtin_msa_srari_w: - case Mips::BI__builtin_msa_srli_w: - case Mips::BI__builtin_msa_srlri_w: - case Mips::BI__builtin_msa_subvi_b: - case Mips::BI__builtin_msa_subvi_h: - case Mips::BI__builtin_msa_subvi_w: - case Mips::BI__builtin_msa_subvi_d: i = 1; l = 0; u = 31; break; - case Mips::BI__builtin_msa_binsli_w: - case Mips::BI__builtin_msa_binsri_w: i = 2; l = 0; u = 31; break; - // These intrinsics take an unsigned 6 bit immediate. - case Mips::BI__builtin_msa_bclri_d: - case Mips::BI__builtin_msa_bnegi_d: - case Mips::BI__builtin_msa_bseti_d: - case Mips::BI__builtin_msa_sat_s_d: - case Mips::BI__builtin_msa_sat_u_d: - case Mips::BI__builtin_msa_slli_d: - case Mips::BI__builtin_msa_srai_d: - case Mips::BI__builtin_msa_srari_d: - case Mips::BI__builtin_msa_srli_d: - case Mips::BI__builtin_msa_srlri_d: i = 1; l = 0; u = 63; break; - case Mips::BI__builtin_msa_binsli_d: - case Mips::BI__builtin_msa_binsri_d: i = 2; l = 0; u = 63; break; - // These intrinsics take a signed 5 bit immediate. - case Mips::BI__builtin_msa_ceqi_b: - case Mips::BI__builtin_msa_ceqi_h: - case Mips::BI__builtin_msa_ceqi_w: - case Mips::BI__builtin_msa_ceqi_d: - case Mips::BI__builtin_msa_clti_s_b: - case Mips::BI__builtin_msa_clti_s_h: - case Mips::BI__builtin_msa_clti_s_w: - case Mips::BI__builtin_msa_clti_s_d: - case Mips::BI__builtin_msa_clei_s_b: - case Mips::BI__builtin_msa_clei_s_h: - case Mips::BI__builtin_msa_clei_s_w: - case Mips::BI__builtin_msa_clei_s_d: - case Mips::BI__builtin_msa_maxi_s_b: - case Mips::BI__builtin_msa_maxi_s_h: - case Mips::BI__builtin_msa_maxi_s_w: - case Mips::BI__builtin_msa_maxi_s_d: - case Mips::BI__builtin_msa_mini_s_b: - case Mips::BI__builtin_msa_mini_s_h: - case Mips::BI__builtin_msa_mini_s_w: - case Mips::BI__builtin_msa_mini_s_d: i = 1; l = -16; u = 15; break; - // These intrinsics take an unsigned 8 bit immediate. - case Mips::BI__builtin_msa_andi_b: - case Mips::BI__builtin_msa_nori_b: - case Mips::BI__builtin_msa_ori_b: - case Mips::BI__builtin_msa_shf_b: - case Mips::BI__builtin_msa_shf_h: - case Mips::BI__builtin_msa_shf_w: - case Mips::BI__builtin_msa_xori_b: i = 1; l = 0; u = 255; break; - case Mips::BI__builtin_msa_bseli_b: - case Mips::BI__builtin_msa_bmnzi_b: - case Mips::BI__builtin_msa_bmzi_b: i = 2; l = 0; u = 255; break; - // df/n format - // These intrinsics take an unsigned 4 bit immediate. - case Mips::BI__builtin_msa_copy_s_b: - case Mips::BI__builtin_msa_copy_u_b: - case Mips::BI__builtin_msa_insve_b: - case Mips::BI__builtin_msa_splati_b: i = 1; l = 0; u = 15; break; - case Mips::BI__builtin_msa_sld_b: - case Mips::BI__builtin_msa_sldi_b: i = 2; l = 0; u = 15; break; - // These intrinsics take an unsigned 3 bit immediate. - case Mips::BI__builtin_msa_copy_s_h: - case Mips::BI__builtin_msa_copy_u_h: - case Mips::BI__builtin_msa_insve_h: - case Mips::BI__builtin_msa_splati_h: i = 1; l = 0; u = 7; break; - case Mips::BI__builtin_msa_sld_h: - case Mips::BI__builtin_msa_sldi_h: i = 2; l = 0; u = 7; break; - // These intrinsics take an unsigned 2 bit immediate. - case Mips::BI__builtin_msa_copy_s_w: - case Mips::BI__builtin_msa_copy_u_w: - case Mips::BI__builtin_msa_insve_w: - case Mips::BI__builtin_msa_splati_w: i = 1; l = 0; u = 3; break; - case Mips::BI__builtin_msa_sld_w: - case Mips::BI__builtin_msa_sldi_w: i = 2; l = 0; u = 3; break; - // These intrinsics take an unsigned 1 bit immediate. - case Mips::BI__builtin_msa_copy_s_d: - case Mips::BI__builtin_msa_copy_u_d: - case Mips::BI__builtin_msa_insve_d: - case Mips::BI__builtin_msa_splati_d: i = 1; l = 0; u = 1; break; - case Mips::BI__builtin_msa_sld_d: - case Mips::BI__builtin_msa_sldi_d: i = 2; l = 0; u = 1; break; - // Memory offsets and immediate loads. - // These intrinsics take a signed 10 bit immediate. - case Mips::BI__builtin_msa_ldi_b: i = 0; l = -128; u = 127; break; - case Mips::BI__builtin_msa_ldi_h: - case Mips::BI__builtin_msa_ldi_w: - case Mips::BI__builtin_msa_ldi_d: i = 0; l = -512; u = 511; break; - case Mips::BI__builtin_msa_ld_b: i = 1; l = -512; u = 511; m = 16; break; - case Mips::BI__builtin_msa_ld_h: i = 1; l = -1024; u = 1022; m = 16; break; - case Mips::BI__builtin_msa_ld_w: i = 1; l = -2048; u = 2044; m = 16; break; - case Mips::BI__builtin_msa_ld_d: i = 1; l = -4096; u = 4088; m = 16; break; - case Mips::BI__builtin_msa_st_b: i = 2; l = -512; u = 511; m = 16; break; - case Mips::BI__builtin_msa_st_h: i = 2; l = -1024; u = 1022; m = 16; break; - case Mips::BI__builtin_msa_st_w: i = 2; l = -2048; u = 2044; m = 16; break; - case Mips::BI__builtin_msa_st_d: i = 2; l = -4096; u = 4088; m = 16; break; - } - - if (!m) - return SemaBuiltinConstantArgRange(TheCall, i, l, u); - - return SemaBuiltinConstantArgRange(TheCall, i, l, u) || - SemaBuiltinConstantArgMultiple(TheCall, i, m); + } + + return SemaBuiltinConstantArgRange(TheCall, i, l, u); } bool Sema::CheckPPCBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { @@ -1784,245 +1090,20 @@ static bool SemaBuiltinCpuSupports(Sema &S, CallExpr *TheCall) { return false; } -// Check if the rounding mode is legal. -bool Sema::CheckX86BuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall) { - // Indicates if this instruction has rounding control or just SAE. - bool HasRC = false; - - unsigned ArgNum = 0; - switch (BuiltinID) { - default: - return false; - case X86::BI__builtin_ia32_vcvttsd2si32: - case X86::BI__builtin_ia32_vcvttsd2si64: - case X86::BI__builtin_ia32_vcvttsd2usi32: - case X86::BI__builtin_ia32_vcvttsd2usi64: - case X86::BI__builtin_ia32_vcvttss2si32: - case X86::BI__builtin_ia32_vcvttss2si64: - case X86::BI__builtin_ia32_vcvttss2usi32: - case X86::BI__builtin_ia32_vcvttss2usi64: - ArgNum = 1; - break; - case X86::BI__builtin_ia32_cvtps2pd512_mask: - case X86::BI__builtin_ia32_cvttpd2dq512_mask: - case X86::BI__builtin_ia32_cvttpd2qq512_mask: - case X86::BI__builtin_ia32_cvttpd2udq512_mask: - case X86::BI__builtin_ia32_cvttpd2uqq512_mask: - case X86::BI__builtin_ia32_cvttps2dq512_mask: - case X86::BI__builtin_ia32_cvttps2qq512_mask: - case X86::BI__builtin_ia32_cvttps2udq512_mask: - case X86::BI__builtin_ia32_cvttps2uqq512_mask: - case X86::BI__builtin_ia32_exp2pd_mask: - case X86::BI__builtin_ia32_exp2ps_mask: - case X86::BI__builtin_ia32_getexppd512_mask: - case X86::BI__builtin_ia32_getexpps512_mask: - case X86::BI__builtin_ia32_rcp28pd_mask: - case X86::BI__builtin_ia32_rcp28ps_mask: - case X86::BI__builtin_ia32_rsqrt28pd_mask: - case X86::BI__builtin_ia32_rsqrt28ps_mask: - case X86::BI__builtin_ia32_vcomisd: - case X86::BI__builtin_ia32_vcomiss: - case X86::BI__builtin_ia32_vcvtph2ps512_mask: - ArgNum = 3; - break; - case X86::BI__builtin_ia32_cmppd512_mask: - case X86::BI__builtin_ia32_cmpps512_mask: - case X86::BI__builtin_ia32_cmpsd_mask: - case X86::BI__builtin_ia32_cmpss_mask: - case X86::BI__builtin_ia32_cvtss2sd_round_mask: - case X86::BI__builtin_ia32_getexpsd128_round_mask: - case X86::BI__builtin_ia32_getexpss128_round_mask: - case X86::BI__builtin_ia32_maxpd512_mask: - case X86::BI__builtin_ia32_maxps512_mask: - case X86::BI__builtin_ia32_maxsd_round_mask: - case X86::BI__builtin_ia32_maxss_round_mask: - case X86::BI__builtin_ia32_minpd512_mask: - case X86::BI__builtin_ia32_minps512_mask: - case X86::BI__builtin_ia32_minsd_round_mask: - case X86::BI__builtin_ia32_minss_round_mask: - case X86::BI__builtin_ia32_rcp28sd_round_mask: - case X86::BI__builtin_ia32_rcp28ss_round_mask: - case X86::BI__builtin_ia32_reducepd512_mask: - case X86::BI__builtin_ia32_reduceps512_mask: - case X86::BI__builtin_ia32_rndscalepd_mask: - case X86::BI__builtin_ia32_rndscaleps_mask: - case X86::BI__builtin_ia32_rsqrt28sd_round_mask: - case X86::BI__builtin_ia32_rsqrt28ss_round_mask: - ArgNum = 4; - break; - case X86::BI__builtin_ia32_fixupimmpd512_mask: - case X86::BI__builtin_ia32_fixupimmpd512_maskz: - case X86::BI__builtin_ia32_fixupimmps512_mask: - case X86::BI__builtin_ia32_fixupimmps512_maskz: - case X86::BI__builtin_ia32_fixupimmsd_mask: - case X86::BI__builtin_ia32_fixupimmsd_maskz: - case X86::BI__builtin_ia32_fixupimmss_mask: - case X86::BI__builtin_ia32_fixupimmss_maskz: - case X86::BI__builtin_ia32_rangepd512_mask: - case X86::BI__builtin_ia32_rangeps512_mask: - case X86::BI__builtin_ia32_rangesd128_round_mask: - case X86::BI__builtin_ia32_rangess128_round_mask: - case X86::BI__builtin_ia32_reducesd_mask: - case X86::BI__builtin_ia32_reducess_mask: - case X86::BI__builtin_ia32_rndscalesd_round_mask: - case X86::BI__builtin_ia32_rndscaless_round_mask: - ArgNum = 5; - break; - case X86::BI__builtin_ia32_vcvtsd2si64: - case X86::BI__builtin_ia32_vcvtsd2si32: - case X86::BI__builtin_ia32_vcvtsd2usi32: - case X86::BI__builtin_ia32_vcvtsd2usi64: - case X86::BI__builtin_ia32_vcvtss2si32: - case X86::BI__builtin_ia32_vcvtss2si64: - case X86::BI__builtin_ia32_vcvtss2usi32: - case X86::BI__builtin_ia32_vcvtss2usi64: - ArgNum = 1; - HasRC = true; - break; - case X86::BI__builtin_ia32_cvtsi2sd64: - case X86::BI__builtin_ia32_cvtsi2ss32: - case X86::BI__builtin_ia32_cvtsi2ss64: - case X86::BI__builtin_ia32_cvtusi2sd64: - case X86::BI__builtin_ia32_cvtusi2ss32: - case X86::BI__builtin_ia32_cvtusi2ss64: - ArgNum = 2; - HasRC = true; - break; - case X86::BI__builtin_ia32_cvtdq2ps512_mask: - case X86::BI__builtin_ia32_cvtudq2ps512_mask: - case X86::BI__builtin_ia32_cvtpd2ps512_mask: - case X86::BI__builtin_ia32_cvtpd2qq512_mask: - case X86::BI__builtin_ia32_cvtpd2uqq512_mask: - case X86::BI__builtin_ia32_cvtps2qq512_mask: - case X86::BI__builtin_ia32_cvtps2uqq512_mask: - case X86::BI__builtin_ia32_cvtqq2pd512_mask: - case X86::BI__builtin_ia32_cvtqq2ps512_mask: - case X86::BI__builtin_ia32_cvtuqq2pd512_mask: - case X86::BI__builtin_ia32_cvtuqq2ps512_mask: - case X86::BI__builtin_ia32_sqrtpd512_mask: - case X86::BI__builtin_ia32_sqrtps512_mask: - ArgNum = 3; - HasRC = true; - break; - case X86::BI__builtin_ia32_addpd512_mask: - case X86::BI__builtin_ia32_addps512_mask: - case X86::BI__builtin_ia32_divpd512_mask: - case X86::BI__builtin_ia32_divps512_mask: - case X86::BI__builtin_ia32_mulpd512_mask: - case X86::BI__builtin_ia32_mulps512_mask: - case X86::BI__builtin_ia32_subpd512_mask: - case X86::BI__builtin_ia32_subps512_mask: - case X86::BI__builtin_ia32_addss_round_mask: - case X86::BI__builtin_ia32_addsd_round_mask: - case X86::BI__builtin_ia32_divss_round_mask: - case X86::BI__builtin_ia32_divsd_round_mask: - case X86::BI__builtin_ia32_mulss_round_mask: - case X86::BI__builtin_ia32_mulsd_round_mask: - case X86::BI__builtin_ia32_subss_round_mask: - case X86::BI__builtin_ia32_subsd_round_mask: - case X86::BI__builtin_ia32_scalefpd512_mask: - case X86::BI__builtin_ia32_scalefps512_mask: - case X86::BI__builtin_ia32_scalefsd_round_mask: - case X86::BI__builtin_ia32_scalefss_round_mask: - case X86::BI__builtin_ia32_getmantpd512_mask: - case X86::BI__builtin_ia32_getmantps512_mask: - case X86::BI__builtin_ia32_cvtsd2ss_round_mask: - case X86::BI__builtin_ia32_sqrtsd_round_mask: - case X86::BI__builtin_ia32_sqrtss_round_mask: - case X86::BI__builtin_ia32_vfmaddpd512_mask: - case X86::BI__builtin_ia32_vfmaddpd512_mask3: - case X86::BI__builtin_ia32_vfmaddpd512_maskz: - case X86::BI__builtin_ia32_vfmaddps512_mask: - case X86::BI__builtin_ia32_vfmaddps512_mask3: - case X86::BI__builtin_ia32_vfmaddps512_maskz: - case X86::BI__builtin_ia32_vfmaddsubpd512_mask: - case X86::BI__builtin_ia32_vfmaddsubpd512_mask3: - case X86::BI__builtin_ia32_vfmaddsubpd512_maskz: - case X86::BI__builtin_ia32_vfmaddsubps512_mask: - case X86::BI__builtin_ia32_vfmaddsubps512_mask3: - case X86::BI__builtin_ia32_vfmaddsubps512_maskz: - case X86::BI__builtin_ia32_vfmsubpd512_mask3: - case X86::BI__builtin_ia32_vfmsubps512_mask3: - case X86::BI__builtin_ia32_vfmsubaddpd512_mask3: - case X86::BI__builtin_ia32_vfmsubaddps512_mask3: - case X86::BI__builtin_ia32_vfnmaddpd512_mask: - case X86::BI__builtin_ia32_vfnmaddps512_mask: - case X86::BI__builtin_ia32_vfnmsubpd512_mask: - case X86::BI__builtin_ia32_vfnmsubpd512_mask3: - case X86::BI__builtin_ia32_vfnmsubps512_mask: - case X86::BI__builtin_ia32_vfnmsubps512_mask3: - case X86::BI__builtin_ia32_vfmaddsd3_mask: - case X86::BI__builtin_ia32_vfmaddsd3_maskz: - case X86::BI__builtin_ia32_vfmaddsd3_mask3: - case X86::BI__builtin_ia32_vfmaddss3_mask: - case X86::BI__builtin_ia32_vfmaddss3_maskz: - case X86::BI__builtin_ia32_vfmaddss3_mask3: - ArgNum = 4; - HasRC = true; - break; - case X86::BI__builtin_ia32_getmantsd_round_mask: - case X86::BI__builtin_ia32_getmantss_round_mask: - ArgNum = 5; - HasRC = true; - break; - } - - llvm::APSInt Result; - - // We can't check the value of a dependent argument. - Expr *Arg = TheCall->getArg(ArgNum); - if (Arg->isTypeDependent() || Arg->isValueDependent()) - return false; - - // Check constant-ness first. - if (SemaBuiltinConstantArg(TheCall, ArgNum, Result)) - return true; - - // Make sure rounding mode is either ROUND_CUR_DIRECTION or ROUND_NO_EXC bit - // is set. If the intrinsic has rounding control(bits 1:0), make sure its only - // combined with ROUND_NO_EXC. - if (Result == 4/*ROUND_CUR_DIRECTION*/ || - Result == 8/*ROUND_NO_EXC*/ || - (HasRC && Result.getZExtValue() >= 8 && Result.getZExtValue() <= 11)) - return false; - - return Diag(TheCall->getLocStart(), diag::err_x86_builtin_invalid_rounding) - << Arg->getSourceRange(); -} - bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { - if (BuiltinID == X86::BI__builtin_cpu_supports) + unsigned i = 0, l = 0, u = 0; + switch (BuiltinID) { + default: return false; + case X86::BI__builtin_cpu_supports: return SemaBuiltinCpuSupports(*this, TheCall); - - if (BuiltinID == X86::BI__builtin_ms_va_start) + case X86::BI__builtin_ms_va_start: return SemaBuiltinMSVAStart(TheCall); - - // If the intrinsic has rounding or SAE make sure its valid. - if (CheckX86BuiltinRoundingOrSAE(BuiltinID, TheCall)) - return true; - - // For intrinsics which take an immediate value as part of the instruction, - // range check them here. - int i = 0, l = 0, u = 0; - switch (BuiltinID) { - default: - return false; - case X86::BI_mm_prefetch: - i = 1; l = 0; u = 3; - break; - case X86::BI__builtin_ia32_sha1rnds4: - case X86::BI__builtin_ia32_shuf_f32x4_256_mask: - case X86::BI__builtin_ia32_shuf_f64x2_256_mask: - case X86::BI__builtin_ia32_shuf_i32x4_256_mask: - case X86::BI__builtin_ia32_shuf_i64x2_256_mask: - i = 2; l = 0; u = 3; - break; + case X86::BI_mm_prefetch: i = 1; l = 0; u = 3; break; + case X86::BI__builtin_ia32_sha1rnds4: i = 2, l = 0; u = 3; break; case X86::BI__builtin_ia32_vpermil2pd: case X86::BI__builtin_ia32_vpermil2pd256: case X86::BI__builtin_ia32_vpermil2ps: - case X86::BI__builtin_ia32_vpermil2ps256: - i = 3; l = 0; u = 3; - break; + case X86::BI__builtin_ia32_vpermil2ps256: i = 3, l = 0; u = 3; break; case X86::BI__builtin_ia32_cmpb128_mask: case X86::BI__builtin_ia32_cmpw128_mask: case X86::BI__builtin_ia32_cmpd128_mask: @@ -2046,170 +1127,29 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { case X86::BI__builtin_ia32_ucmpb512_mask: case X86::BI__builtin_ia32_ucmpw512_mask: case X86::BI__builtin_ia32_ucmpd512_mask: - case X86::BI__builtin_ia32_ucmpq512_mask: - case X86::BI__builtin_ia32_vpcomub: - case X86::BI__builtin_ia32_vpcomuw: - case X86::BI__builtin_ia32_vpcomud: - case X86::BI__builtin_ia32_vpcomuq: - case X86::BI__builtin_ia32_vpcomb: - case X86::BI__builtin_ia32_vpcomw: - case X86::BI__builtin_ia32_vpcomd: - case X86::BI__builtin_ia32_vpcomq: - i = 2; l = 0; u = 7; - break; + case X86::BI__builtin_ia32_ucmpq512_mask: i = 2; l = 0; u = 7; break; case X86::BI__builtin_ia32_roundps: case X86::BI__builtin_ia32_roundpd: case X86::BI__builtin_ia32_roundps256: - case X86::BI__builtin_ia32_roundpd256: - i = 1; l = 0; u = 15; - break; + case X86::BI__builtin_ia32_roundpd256: i = 1, l = 0; u = 15; break; case X86::BI__builtin_ia32_roundss: - case X86::BI__builtin_ia32_roundsd: - case X86::BI__builtin_ia32_rangepd128_mask: - case X86::BI__builtin_ia32_rangepd256_mask: - case X86::BI__builtin_ia32_rangepd512_mask: - case X86::BI__builtin_ia32_rangeps128_mask: - case X86::BI__builtin_ia32_rangeps256_mask: - case X86::BI__builtin_ia32_rangeps512_mask: - case X86::BI__builtin_ia32_getmantsd_round_mask: - case X86::BI__builtin_ia32_getmantss_round_mask: - i = 2; l = 0; u = 15; - break; + case X86::BI__builtin_ia32_roundsd: i = 2, l = 0; u = 15; break; case X86::BI__builtin_ia32_cmpps: case X86::BI__builtin_ia32_cmpss: case X86::BI__builtin_ia32_cmppd: case X86::BI__builtin_ia32_cmpsd: case X86::BI__builtin_ia32_cmpps256: case X86::BI__builtin_ia32_cmppd256: - case X86::BI__builtin_ia32_cmpps128_mask: - case X86::BI__builtin_ia32_cmppd128_mask: - case X86::BI__builtin_ia32_cmpps256_mask: - case X86::BI__builtin_ia32_cmppd256_mask: case X86::BI__builtin_ia32_cmpps512_mask: - case X86::BI__builtin_ia32_cmppd512_mask: - case X86::BI__builtin_ia32_cmpsd_mask: - case X86::BI__builtin_ia32_cmpss_mask: - i = 2; l = 0; u = 31; - break; - case X86::BI__builtin_ia32_xabort: - i = 0; l = -128; u = 255; - break; - case X86::BI__builtin_ia32_pshufw: - case X86::BI__builtin_ia32_aeskeygenassist128: - i = 1; l = -128; u = 255; - break; - case X86::BI__builtin_ia32_vcvtps2ph: - case X86::BI__builtin_ia32_vcvtps2ph256: - case X86::BI__builtin_ia32_rndscaleps_128_mask: - case X86::BI__builtin_ia32_rndscalepd_128_mask: - case X86::BI__builtin_ia32_rndscaleps_256_mask: - case X86::BI__builtin_ia32_rndscalepd_256_mask: - case X86::BI__builtin_ia32_rndscaleps_mask: - case X86::BI__builtin_ia32_rndscalepd_mask: - case X86::BI__builtin_ia32_reducepd128_mask: - case X86::BI__builtin_ia32_reducepd256_mask: - case X86::BI__builtin_ia32_reducepd512_mask: - case X86::BI__builtin_ia32_reduceps128_mask: - case X86::BI__builtin_ia32_reduceps256_mask: - case X86::BI__builtin_ia32_reduceps512_mask: - case X86::BI__builtin_ia32_prold512_mask: - case X86::BI__builtin_ia32_prolq512_mask: - case X86::BI__builtin_ia32_prold128_mask: - case X86::BI__builtin_ia32_prold256_mask: - case X86::BI__builtin_ia32_prolq128_mask: - case X86::BI__builtin_ia32_prolq256_mask: - case X86::BI__builtin_ia32_prord128_mask: - case X86::BI__builtin_ia32_prord256_mask: - case X86::BI__builtin_ia32_prorq128_mask: - case X86::BI__builtin_ia32_prorq256_mask: - case X86::BI__builtin_ia32_fpclasspd128_mask: - case X86::BI__builtin_ia32_fpclasspd256_mask: - case X86::BI__builtin_ia32_fpclassps128_mask: - case X86::BI__builtin_ia32_fpclassps256_mask: - case X86::BI__builtin_ia32_fpclassps512_mask: - case X86::BI__builtin_ia32_fpclasspd512_mask: - case X86::BI__builtin_ia32_fpclasssd_mask: - case X86::BI__builtin_ia32_fpclassss_mask: - i = 1; l = 0; u = 255; - break; - case X86::BI__builtin_ia32_palignr: - case X86::BI__builtin_ia32_insertps128: - case X86::BI__builtin_ia32_dpps: - case X86::BI__builtin_ia32_dppd: - case X86::BI__builtin_ia32_dpps256: - case X86::BI__builtin_ia32_mpsadbw128: - case X86::BI__builtin_ia32_mpsadbw256: - case X86::BI__builtin_ia32_pcmpistrm128: - case X86::BI__builtin_ia32_pcmpistri128: - case X86::BI__builtin_ia32_pcmpistria128: - case X86::BI__builtin_ia32_pcmpistric128: - case X86::BI__builtin_ia32_pcmpistrio128: - case X86::BI__builtin_ia32_pcmpistris128: - case X86::BI__builtin_ia32_pcmpistriz128: - case X86::BI__builtin_ia32_pclmulqdq128: - case X86::BI__builtin_ia32_vperm2f128_pd256: - case X86::BI__builtin_ia32_vperm2f128_ps256: - case X86::BI__builtin_ia32_vperm2f128_si256: - case X86::BI__builtin_ia32_permti256: - i = 2; l = -128; u = 255; - break; - case X86::BI__builtin_ia32_palignr128: - case X86::BI__builtin_ia32_palignr256: - case X86::BI__builtin_ia32_palignr512_mask: - case X86::BI__builtin_ia32_vcomisd: - case X86::BI__builtin_ia32_vcomiss: - case X86::BI__builtin_ia32_shuf_f32x4_mask: - case X86::BI__builtin_ia32_shuf_f64x2_mask: - case X86::BI__builtin_ia32_shuf_i32x4_mask: - case X86::BI__builtin_ia32_shuf_i64x2_mask: - case X86::BI__builtin_ia32_dbpsadbw128_mask: - case X86::BI__builtin_ia32_dbpsadbw256_mask: - case X86::BI__builtin_ia32_dbpsadbw512_mask: - i = 2; l = 0; u = 255; - break; - case X86::BI__builtin_ia32_fixupimmpd512_mask: - case X86::BI__builtin_ia32_fixupimmpd512_maskz: - case X86::BI__builtin_ia32_fixupimmps512_mask: - case X86::BI__builtin_ia32_fixupimmps512_maskz: - case X86::BI__builtin_ia32_fixupimmsd_mask: - case X86::BI__builtin_ia32_fixupimmsd_maskz: - case X86::BI__builtin_ia32_fixupimmss_mask: - case X86::BI__builtin_ia32_fixupimmss_maskz: - case X86::BI__builtin_ia32_fixupimmpd128_mask: - case X86::BI__builtin_ia32_fixupimmpd128_maskz: - case X86::BI__builtin_ia32_fixupimmpd256_mask: - case X86::BI__builtin_ia32_fixupimmpd256_maskz: - case X86::BI__builtin_ia32_fixupimmps128_mask: - case X86::BI__builtin_ia32_fixupimmps128_maskz: - case X86::BI__builtin_ia32_fixupimmps256_mask: - case X86::BI__builtin_ia32_fixupimmps256_maskz: - case X86::BI__builtin_ia32_pternlogd512_mask: - case X86::BI__builtin_ia32_pternlogd512_maskz: - case X86::BI__builtin_ia32_pternlogq512_mask: - case X86::BI__builtin_ia32_pternlogq512_maskz: - case X86::BI__builtin_ia32_pternlogd128_mask: - case X86::BI__builtin_ia32_pternlogd128_maskz: - case X86::BI__builtin_ia32_pternlogd256_mask: - case X86::BI__builtin_ia32_pternlogd256_maskz: - case X86::BI__builtin_ia32_pternlogq128_mask: - case X86::BI__builtin_ia32_pternlogq128_maskz: - case X86::BI__builtin_ia32_pternlogq256_mask: - case X86::BI__builtin_ia32_pternlogq256_maskz: - i = 3; l = 0; u = 255; - break; - case X86::BI__builtin_ia32_pcmpestrm128: - case X86::BI__builtin_ia32_pcmpestri128: - case X86::BI__builtin_ia32_pcmpestria128: - case X86::BI__builtin_ia32_pcmpestric128: - case X86::BI__builtin_ia32_pcmpestrio128: - case X86::BI__builtin_ia32_pcmpestris128: - case X86::BI__builtin_ia32_pcmpestriz128: - i = 4; l = -128; u = 255; - break; - case X86::BI__builtin_ia32_rndscalesd_round_mask: - case X86::BI__builtin_ia32_rndscaless_round_mask: - i = 4; l = 0; u = 255; - break; + case X86::BI__builtin_ia32_cmppd512_mask: i = 2; l = 0; u = 31; break; + case X86::BI__builtin_ia32_vpcomub: + case X86::BI__builtin_ia32_vpcomuw: + case X86::BI__builtin_ia32_vpcomud: + case X86::BI__builtin_ia32_vpcomuq: + case X86::BI__builtin_ia32_vpcomb: + case X86::BI__builtin_ia32_vpcomw: + case X86::BI__builtin_ia32_vpcomd: + case X86::BI__builtin_ia32_vpcomq: i = 2; l = 0; u = 7; break; } return SemaBuiltinConstantArgRange(TheCall, i, l, u); } @@ -2426,12 +1366,11 @@ static void CheckNonNullArguments(Sema &S, } /// Handles the checks for format strings, non-POD arguments to vararg -/// functions, NULL arguments passed to non-NULL parameters, and diagnose_if -/// attributes. +/// functions, and NULL arguments passed to non-NULL parameters. void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto, - const Expr *ThisArg, ArrayRef<const Expr *> Args, - bool IsMemberFunction, SourceLocation Loc, - SourceRange Range, VariadicCallType CallType) { + ArrayRef<const Expr *> Args, bool IsMemberFunction, + SourceLocation Loc, SourceRange Range, + VariadicCallType CallType) { // FIXME: We should check as much as we can in the template definition. if (CurContext->isDependentContext()) return; @@ -2450,9 +1389,7 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto, // Refuse POD arguments that weren't caught by the format string // checks above. - auto *FD = dyn_cast_or_null<FunctionDecl>(FDecl); - if (CallType != VariadicDoesNotApply && - (!FD || FD->getBuiltinID() != Builtin::BI__noop)) { + if (CallType != VariadicDoesNotApply) { unsigned NumParams = Proto ? Proto->getNumParams() : FDecl && isa<FunctionDecl>(FDecl) ? cast<FunctionDecl>(FDecl)->getNumParams() @@ -2478,9 +1415,6 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto, CheckArgumentWithTypeTag(I, Args.data()); } } - - if (FD) - diagnoseArgDependentDiagnoseIfAttrs(FD, ThisArg, Args, Loc); } /// CheckConstructorCall - Check a constructor call for correctness and safety @@ -2491,8 +1425,8 @@ void Sema::CheckConstructorCall(FunctionDecl *FDecl, SourceLocation Loc) { VariadicCallType CallType = Proto->isVariadic() ? VariadicConstructor : VariadicDoesNotApply; - checkCall(FDecl, Proto, /*ThisArg=*/nullptr, Args, /*IsMemberFunction=*/true, - Loc, SourceRange(), CallType); + checkCall(FDecl, Proto, Args, /*IsMemberFunction=*/true, Loc, SourceRange(), + CallType); } /// CheckFunctionCall - Check a direct function call for various correctness @@ -2507,20 +1441,14 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall, TheCall->getCallee()); Expr** Args = TheCall->getArgs(); unsigned NumArgs = TheCall->getNumArgs(); - - Expr *ImplicitThis = nullptr; if (IsMemberOperatorCall) { // If this is a call to a member operator, hide the first argument // from checkCall. // FIXME: Our choice of AST representation here is less than ideal. - ImplicitThis = Args[0]; ++Args; --NumArgs; - } else if (IsMemberFunction) - ImplicitThis = - cast<CXXMemberCallExpr>(TheCall)->getImplicitObjectArgument(); - - checkCall(FDecl, Proto, ImplicitThis, llvm::makeArrayRef(Args, NumArgs), + } + checkCall(FDecl, Proto, llvm::makeArrayRef(Args, NumArgs), IsMemberFunction, TheCall->getRParenLoc(), TheCall->getCallee()->getSourceRange(), CallType); @@ -2530,9 +1458,7 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall, if (!FnInfo) return false; - CheckAbsoluteValueFunction(TheCall, FDecl); - CheckMaxUnsignedZero(TheCall, FDecl); - + CheckAbsoluteValueFunction(TheCall, FDecl, FnInfo); if (getLangOpts().ObjC1) DiagnoseCStringFormatDirectiveInCFAPI(*this, FDecl, Args, NumArgs); @@ -2556,8 +1482,8 @@ bool Sema::CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation lbrac, VariadicCallType CallType = Method->isVariadic() ? VariadicMethod : VariadicDoesNotApply; - checkCall(Method, nullptr, /*ThisArg=*/nullptr, Args, - /*IsMemberFunction=*/false, lbrac, Method->getSourceRange(), + checkCall(Method, nullptr, Args, + /*IsMemberFunction=*/false, lbrac, Method->getSourceRange(), CallType); return false; @@ -2586,7 +1512,7 @@ bool Sema::CheckPointerCall(NamedDecl *NDecl, CallExpr *TheCall, CallType = VariadicFunction; } - checkCall(NDecl, Proto, /*ThisArg=*/nullptr, + checkCall(NDecl, Proto, llvm::makeArrayRef(TheCall->getArgs(), TheCall->getNumArgs()), /*IsMemberFunction=*/false, TheCall->getRParenLoc(), TheCall->getCallee()->getSourceRange(), CallType); @@ -2599,7 +1525,7 @@ bool Sema::CheckPointerCall(NamedDecl *NDecl, CallExpr *TheCall, bool Sema::CheckOtherCall(CallExpr *TheCall, const FunctionProtoType *Proto) { VariadicCallType CallType = getVariadicCallType(/*FDecl=*/nullptr, Proto, TheCall->getCallee()); - checkCall(/*FDecl=*/nullptr, Proto, /*ThisArg=*/nullptr, + checkCall(/*FDecl=*/nullptr, Proto, llvm::makeArrayRef(TheCall->getArgs(), TheCall->getNumArgs()), /*IsMemberFunction=*/false, TheCall->getRParenLoc(), TheCall->getCallee()->getSourceRange(), CallType); @@ -2608,10 +1534,10 @@ bool Sema::CheckOtherCall(CallExpr *TheCall, const FunctionProtoType *Proto) { } static bool isValidOrderingForOp(int64_t Ordering, AtomicExpr::AtomicOp Op) { - if (!llvm::isValidAtomicOrderingCABI(Ordering)) + if (Ordering < AtomicExpr::AO_ABI_memory_order_relaxed || + Ordering > AtomicExpr::AO_ABI_memory_order_seq_cst) return false; - auto OrderingCABI = (llvm::AtomicOrderingCABI)Ordering; switch (Op) { case AtomicExpr::AO__c11_atomic_init: llvm_unreachable("There is no ordering argument for an init"); @@ -2619,15 +1545,15 @@ static bool isValidOrderingForOp(int64_t Ordering, AtomicExpr::AtomicOp Op) { case AtomicExpr::AO__c11_atomic_load: case AtomicExpr::AO__atomic_load_n: case AtomicExpr::AO__atomic_load: - return OrderingCABI != llvm::AtomicOrderingCABI::release && - OrderingCABI != llvm::AtomicOrderingCABI::acq_rel; + return Ordering != AtomicExpr::AO_ABI_memory_order_release && + Ordering != AtomicExpr::AO_ABI_memory_order_acq_rel; case AtomicExpr::AO__c11_atomic_store: case AtomicExpr::AO__atomic_store: case AtomicExpr::AO__atomic_store_n: - return OrderingCABI != llvm::AtomicOrderingCABI::consume && - OrderingCABI != llvm::AtomicOrderingCABI::acquire && - OrderingCABI != llvm::AtomicOrderingCABI::acq_rel; + return Ordering != AtomicExpr::AO_ABI_memory_order_consume && + Ordering != AtomicExpr::AO_ABI_memory_order_acquire && + Ordering != AtomicExpr::AO_ABI_memory_order_acq_rel; default: return true; @@ -2646,8 +1572,6 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, // C __c11_atomic_load(A *, int) Load, // void __atomic_load(A *, CP, int) - LoadCopy, - // void __atomic_store(A *, CP, int) Copy, // C __c11_atomic_add(A *, M, int) Arithmetic, @@ -2660,8 +1584,8 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, // bool __atomic_compare_exchange(A *, C *, CP, bool, int, int) GNUCmpXchg } Form = Init; - const unsigned NumArgs[] = { 2, 2, 3, 3, 3, 3, 4, 5, 6 }; - const unsigned NumVals[] = { 1, 0, 1, 1, 1, 1, 2, 2, 3 }; + const unsigned NumArgs[] = { 2, 2, 3, 3, 3, 4, 5, 6 }; + const unsigned NumVals[] = { 1, 0, 1, 1, 1, 2, 2, 3 }; // where: // C is an appropriate type, // A is volatile _Atomic(C) for __c11 builtins and is C for GNU builtins, @@ -2691,11 +1615,8 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, Form = Load; break; - case AtomicExpr::AO__atomic_load: - Form = LoadCopy; - break; - case AtomicExpr::AO__c11_atomic_store: + case AtomicExpr::AO__atomic_load: case AtomicExpr::AO__atomic_store: case AtomicExpr::AO__atomic_store_n: Form = Copy; @@ -2759,11 +1680,7 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, // Inspect the first argument of the atomic operation. Expr *Ptr = TheCall->getArg(0); - ExprResult ConvertedPtr = DefaultFunctionArrayLvalueConversion(Ptr); - if (ConvertedPtr.isInvalid()) - return ExprError(); - - Ptr = ConvertedPtr.get(); + Ptr = DefaultFunctionArrayLvalueConversion(Ptr).get(); const PointerType *pointerType = Ptr->getType()->getAs<PointerType>(); if (!pointerType) { Diag(DRE->getLocStart(), diag::err_atomic_builtin_must_be_pointer) @@ -2786,7 +1703,7 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, return ExprError(); } ValType = AtomTy->getAs<AtomicType>()->getValueType(); - } else if (Form != Load && Form != LoadCopy) { + } else if (Form != Load && Op != AtomicExpr::AO__atomic_load) { if (ValType.isConstQualified()) { Diag(DRE->getLocStart(), diag::err_atomic_op_needs_non_const_pointer) << Ptr->getType() << Ptr->getSourceRange(); @@ -2847,11 +1764,10 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, // atomic_fetch_or takes a pointer to a volatile 'A'. We shouldn't let the // volatile-ness of the pointee-type inject itself into the result or the - // other operands. Similarly atomic_load can take a pointer to a const 'A'. + // other operands. ValType.removeLocalVolatile(); - ValType.removeLocalConst(); QualType ResultType = ValType; - if (Form == Copy || Form == LoadCopy || Form == GNUXchg || Form == Init) + if (Form == Copy || Form == GNUXchg || Form == Init) ResultType = Context.VoidTy; else if (Form == C11CmpXchg || Form == GNUCmpXchg) ResultType = Context.BoolTy; @@ -2862,6 +1778,10 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, if (!IsC11 && !IsN) ByValType = Ptr->getType(); + // FIXME: __atomic_load allows the first argument to be a a pointer to const + // but not the second argument. We need to manually remove possible const + // qualifiers. + // The first argument --- the pointer --- has a fixed type; we // deduce the types of the rest of the arguments accordingly. Walk // the remaining arguments, converting them to the deduced value type. @@ -2883,9 +1803,6 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, Ty = Context.getPointerDiffType(); else { Expr *ValArg = TheCall->getArg(i); - // Treat this argument as _Nonnull as we want to show a warning if - // NULL is passed into it. - CheckNonNullArgument(*this, ValArg, DRE->getLocStart()); unsigned AS = 0; // Keep address space of non-atomic pointer type. if (const PointerType *PtrTy = @@ -2931,7 +1848,6 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, case Load: SubExprs.push_back(TheCall->getArg(1)); // Order break; - case LoadCopy: case Copy: case Arithmetic: case Xchg: @@ -2981,6 +1897,7 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, return AE; } + /// checkBuiltinArgument - Given a call to a builtin function, perform /// normal type-checking on the given argument, updating the call in /// place. This is useful when a builtin function requires custom @@ -3462,46 +2379,21 @@ bool Sema::CheckObjCString(Expr *Arg) { if (Literal->containsNonAsciiOrNull()) { StringRef String = Literal->getString(); unsigned NumBytes = String.size(); - SmallVector<llvm::UTF16, 128> ToBuf(NumBytes); - const llvm::UTF8 *FromPtr = (const llvm::UTF8 *)String.data(); - llvm::UTF16 *ToPtr = &ToBuf[0]; - - llvm::ConversionResult Result = - llvm::ConvertUTF8toUTF16(&FromPtr, FromPtr + NumBytes, &ToPtr, - ToPtr + NumBytes, llvm::strictConversion); + SmallVector<UTF16, 128> ToBuf(NumBytes); + const UTF8 *FromPtr = (const UTF8 *)String.data(); + UTF16 *ToPtr = &ToBuf[0]; + + ConversionResult Result = ConvertUTF8toUTF16(&FromPtr, FromPtr + NumBytes, + &ToPtr, ToPtr + NumBytes, + strictConversion); // Check for conversion failure. - if (Result != llvm::conversionOK) + if (Result != conversionOK) Diag(Arg->getLocStart(), diag::warn_cfstring_truncated) << Arg->getSourceRange(); } return false; } -/// CheckObjCString - Checks that the format string argument to the os_log() -/// and os_trace() functions is correct, and converts it to const char *. -ExprResult Sema::CheckOSLogFormatStringArg(Expr *Arg) { - Arg = Arg->IgnoreParenCasts(); - auto *Literal = dyn_cast<StringLiteral>(Arg); - if (!Literal) { - if (auto *ObjcLiteral = dyn_cast<ObjCStringLiteral>(Arg)) { - Literal = ObjcLiteral->getString(); - } - } - - if (!Literal || (!Literal->isAscii() && !Literal->isUTF8())) { - return ExprError( - Diag(Arg->getLocStart(), diag::err_os_log_format_not_string_constant) - << Arg->getSourceRange()); - } - - ExprResult Result(Literal); - QualType ResultTy = Context.getPointerType(Context.CharTy.withConst()); - InitializedEntity Entity = - InitializedEntity::InitializeParameter(Context, ResultTy, false); - Result = PerformCopyInitialization(Entity, SourceLocation(), Result); - return Result; -} - /// Check the arguments to '__builtin_va_start' or '__builtin_ms_va_start' /// for validity. Emit an error and return true on failure; return false /// on success. @@ -3551,7 +2443,6 @@ bool Sema::SemaBuiltinVAStartImpl(CallExpr *TheCall) { // block. QualType Type; SourceLocation ParamLoc; - bool IsCRegister = false; if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Arg)) { if (const ParmVarDecl *PV = dyn_cast<ParmVarDecl>(DR->getDecl())) { @@ -3559,39 +2450,24 @@ bool Sema::SemaBuiltinVAStartImpl(CallExpr *TheCall) { // Get the last formal in the current function. const ParmVarDecl *LastArg; if (CurBlock) - LastArg = CurBlock->TheDecl->parameters().back(); + LastArg = *(CurBlock->TheDecl->param_end()-1); else if (FunctionDecl *FD = getCurFunctionDecl()) - LastArg = FD->parameters().back(); + LastArg = *(FD->param_end()-1); else - LastArg = getCurMethodDecl()->parameters().back(); + LastArg = *(getCurMethodDecl()->param_end()-1); SecondArgIsLastNamedArgument = PV == LastArg; Type = PV->getType(); ParamLoc = PV->getLocation(); - IsCRegister = - PV->getStorageClass() == SC_Register && !getLangOpts().CPlusPlus; } } if (!SecondArgIsLastNamedArgument) Diag(TheCall->getArg(1)->getLocStart(), - diag::warn_second_arg_of_va_start_not_last_named_param); - else if (IsCRegister || Type->isReferenceType() || - Type->isSpecificBuiltinType(BuiltinType::Float) || [=] { - // Promotable integers are UB, but enumerations need a bit of - // extra checking to see what their promotable type actually is. - if (!Type->isPromotableIntegerType()) - return false; - if (!Type->isEnumeralType()) - return true; - const EnumDecl *ED = Type->getAs<EnumType>()->getDecl(); - return !(ED && - Context.typesAreCompatible(ED->getPromotionType(), Type)); - }()) { - unsigned Reason = 0; - if (Type->isReferenceType()) Reason = 1; - else if (IsCRegister) Reason = 2; - Diag(Arg->getLocStart(), diag::warn_va_start_type_is_undefined) << Reason; + diag::warn_second_parameter_of_va_start_not_last_named_argument); + else if (Type->isReferenceType()) { + Diag(Arg->getLocStart(), + diag::warn_va_start_of_reference_type_is_undefined); Diag(ParamLoc, diag::note_parameter_type) << Type; } @@ -3761,18 +2637,14 @@ bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs) { diag::err_typecheck_call_invalid_unary_fp) << OrigArg->getType() << OrigArg->getSourceRange(); - // If this is an implicit conversion from float -> float or double, remove it. + // If this is an implicit conversion from float -> double, remove it. if (ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(OrigArg)) { - // Only remove standard FloatCasts, leaving other casts inplace - if (Cast->getCastKind() == CK_FloatingCast) { - Expr *CastArg = Cast->getSubExpr(); - if (CastArg->getType()->isSpecificBuiltinType(BuiltinType::Float)) { - assert((Cast->getType()->isSpecificBuiltinType(BuiltinType::Double) || - Cast->getType()->isSpecificBuiltinType(BuiltinType::Float)) && - "promotion from float to either float or double is the only expected cast here"); - Cast->setSubExpr(nullptr); - TheCall->setArg(NumArgs-1, CastArg); - } + Expr *CastArg = Cast->getSubExpr(); + if (CastArg->getType()->isSpecificBuiltinType(BuiltinType::Float)) { + assert(Cast->getType()->isSpecificBuiltinType(BuiltinType::Double) && + "promotion from float to double is the only expected cast here"); + Cast->setSubExpr(nullptr); + TheCall->setArg(NumArgs-1, CastArg); } } @@ -3790,7 +2662,8 @@ ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) { // Determine which of the following types of shufflevector we're checking: // 1) unary, vector mask: (lhs, mask) - // 2) binary, scalar mask: (lhs, rhs, index, ..., index) + // 2) binary, vector mask: (lhs, rhs, mask) + // 3) binary, scalar mask: (lhs, rhs, index, ..., index) QualType resType = TheCall->getArg(0)->getType(); unsigned numElements = 0; @@ -3929,42 +2802,6 @@ bool Sema::SemaBuiltinAssume(CallExpr *TheCall) { return false; } -/// Handle __builtin_alloca_with_align. This is declared -/// as (size_t, size_t) where the second size_t must be a power of 2 greater -/// than 8. -bool Sema::SemaBuiltinAllocaWithAlign(CallExpr *TheCall) { - // The alignment must be a constant integer. - Expr *Arg = TheCall->getArg(1); - - // We can't check the value of a dependent argument. - if (!Arg->isTypeDependent() && !Arg->isValueDependent()) { - if (const auto *UE = - dyn_cast<UnaryExprOrTypeTraitExpr>(Arg->IgnoreParenImpCasts())) - if (UE->getKind() == UETT_AlignOf) - Diag(TheCall->getLocStart(), diag::warn_alloca_align_alignof) - << Arg->getSourceRange(); - - llvm::APSInt Result = Arg->EvaluateKnownConstInt(Context); - - if (!Result.isPowerOf2()) - return Diag(TheCall->getLocStart(), - diag::err_alignment_not_power_of_two) - << Arg->getSourceRange(); - - if (Result < Context.getCharWidth()) - return Diag(TheCall->getLocStart(), diag::err_alignment_too_small) - << (unsigned)Context.getCharWidth() - << Arg->getSourceRange(); - - if (Result > INT32_MAX) - return Diag(TheCall->getLocStart(), diag::err_alignment_too_big) - << INT32_MAX - << Arg->getSourceRange(); - } - - return false; -} - /// Handle __builtin_assume_aligned. This is declared /// as (const void*, size_t, ...) and can take one optional constant int arg. bool Sema::SemaBuiltinAssumeAligned(CallExpr *TheCall) { @@ -4003,86 +2840,6 @@ bool Sema::SemaBuiltinAssumeAligned(CallExpr *TheCall) { return false; } -bool Sema::SemaBuiltinOSLogFormat(CallExpr *TheCall) { - unsigned BuiltinID = - cast<FunctionDecl>(TheCall->getCalleeDecl())->getBuiltinID(); - bool IsSizeCall = BuiltinID == Builtin::BI__builtin_os_log_format_buffer_size; - - unsigned NumArgs = TheCall->getNumArgs(); - unsigned NumRequiredArgs = IsSizeCall ? 1 : 2; - if (NumArgs < NumRequiredArgs) { - return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args) - << 0 /* function call */ << NumRequiredArgs << NumArgs - << TheCall->getSourceRange(); - } - if (NumArgs >= NumRequiredArgs + 0x100) { - return Diag(TheCall->getLocEnd(), - diag::err_typecheck_call_too_many_args_at_most) - << 0 /* function call */ << (NumRequiredArgs + 0xff) << NumArgs - << TheCall->getSourceRange(); - } - unsigned i = 0; - - // For formatting call, check buffer arg. - if (!IsSizeCall) { - ExprResult Arg(TheCall->getArg(i)); - InitializedEntity Entity = InitializedEntity::InitializeParameter( - Context, Context.VoidPtrTy, false); - Arg = PerformCopyInitialization(Entity, SourceLocation(), Arg); - if (Arg.isInvalid()) - return true; - TheCall->setArg(i, Arg.get()); - i++; - } - - // Check string literal arg. - unsigned FormatIdx = i; - { - ExprResult Arg = CheckOSLogFormatStringArg(TheCall->getArg(i)); - if (Arg.isInvalid()) - return true; - TheCall->setArg(i, Arg.get()); - i++; - } - - // Make sure variadic args are scalar. - unsigned FirstDataArg = i; - while (i < NumArgs) { - ExprResult Arg = DefaultVariadicArgumentPromotion( - TheCall->getArg(i), VariadicFunction, nullptr); - if (Arg.isInvalid()) - return true; - CharUnits ArgSize = Context.getTypeSizeInChars(Arg.get()->getType()); - if (ArgSize.getQuantity() >= 0x100) { - return Diag(Arg.get()->getLocEnd(), diag::err_os_log_argument_too_big) - << i << (int)ArgSize.getQuantity() << 0xff - << TheCall->getSourceRange(); - } - TheCall->setArg(i, Arg.get()); - i++; - } - - // Check formatting specifiers. NOTE: We're only doing this for the non-size - // call to avoid duplicate diagnostics. - if (!IsSizeCall) { - llvm::SmallBitVector CheckedVarArgs(NumArgs, false); - ArrayRef<const Expr *> Args(TheCall->getArgs(), TheCall->getNumArgs()); - bool Success = CheckFormatArguments( - Args, /*HasVAListArg*/ false, FormatIdx, FirstDataArg, FST_OSLog, - VariadicFunction, TheCall->getLocStart(), SourceRange(), - CheckedVarArgs); - if (!Success) - return true; - } - - if (IsSizeCall) { - TheCall->setType(Context.getSizeType()); - } else { - TheCall->setType(Context.VoidPtrTy); - } - return false; -} - /// SemaBuiltinConstantArg - Handle a check if argument ArgNum of CallExpr /// TheCall is a constant expression. bool Sema::SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum, @@ -4122,28 +2879,6 @@ bool Sema::SemaBuiltinConstantArgRange(CallExpr *TheCall, int ArgNum, return false; } -/// SemaBuiltinConstantArgMultiple - Handle a check if argument ArgNum of CallExpr -/// TheCall is a constant expression is a multiple of Num.. -bool Sema::SemaBuiltinConstantArgMultiple(CallExpr *TheCall, int ArgNum, - unsigned Num) { - llvm::APSInt Result; - - // We can't check the value of a dependent argument. - Expr *Arg = TheCall->getArg(ArgNum); - if (Arg->isTypeDependent() || Arg->isValueDependent()) - return false; - - // Check constant-ness first. - if (SemaBuiltinConstantArg(TheCall, ArgNum, Result)) - return true; - - if (Result.getSExtValue() % Num != 0) - return Diag(TheCall->getLocStart(), diag::err_argument_not_multiple) - << Num << Arg->getSourceRange(); - - return false; -} - /// SemaBuiltinARMSpecialReg - Handle a check if argument ArgNum of CallExpr /// TheCall is an ARM/AArch64 special register string literal. bool Sema::SemaBuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall, @@ -4210,7 +2945,7 @@ bool Sema::SemaBuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall, SmallVector<int, 5> Ranges; if (FiveFields) - Ranges.append({IsAArch64Builtin ? 1 : 15, 7, 15, 15, 7}); + Ranges.append({IsAArch64Builtin ? 1 : 15, 7, 7, 15, 15}); else Ranges.append({15, 7, 15}); @@ -4267,6 +3002,7 @@ bool Sema::SemaBuiltinLongjmp(CallExpr *TheCall) { return false; } + /// SemaBuiltinSetjmp - Handle __builtin_setjmp(void *env[5]). /// This checks that the target supports __builtin_setjmp. bool Sema::SemaBuiltinSetjmp(CallExpr *TheCall) { @@ -4277,157 +3013,13 @@ bool Sema::SemaBuiltinSetjmp(CallExpr *TheCall) { } namespace { -class UncoveredArgHandler { - enum { Unknown = -1, AllCovered = -2 }; - signed FirstUncoveredArg; - SmallVector<const Expr *, 4> DiagnosticExprs; - -public: - UncoveredArgHandler() : FirstUncoveredArg(Unknown) { } - - bool hasUncoveredArg() const { - return (FirstUncoveredArg >= 0); - } - - unsigned getUncoveredArg() const { - assert(hasUncoveredArg() && "no uncovered argument"); - return FirstUncoveredArg; - } - - void setAllCovered() { - // A string has been found with all arguments covered, so clear out - // the diagnostics. - DiagnosticExprs.clear(); - FirstUncoveredArg = AllCovered; - } - - void Update(signed NewFirstUncoveredArg, const Expr *StrExpr) { - assert(NewFirstUncoveredArg >= 0 && "Outside range"); - - // Don't update if a previous string covers all arguments. - if (FirstUncoveredArg == AllCovered) - return; - - // UncoveredArgHandler tracks the highest uncovered argument index - // and with it all the strings that match this index. - if (NewFirstUncoveredArg == FirstUncoveredArg) - DiagnosticExprs.push_back(StrExpr); - else if (NewFirstUncoveredArg > FirstUncoveredArg) { - DiagnosticExprs.clear(); - DiagnosticExprs.push_back(StrExpr); - FirstUncoveredArg = NewFirstUncoveredArg; - } - } - - void Diagnose(Sema &S, bool IsFunctionCall, const Expr *ArgExpr); -}; - enum StringLiteralCheckType { SLCT_NotALiteral, SLCT_UncheckedLiteral, SLCT_CheckedLiteral }; -} // end anonymous namespace - -static void sumOffsets(llvm::APSInt &Offset, llvm::APSInt Addend, - BinaryOperatorKind BinOpKind, - bool AddendIsRight) { - unsigned BitWidth = Offset.getBitWidth(); - unsigned AddendBitWidth = Addend.getBitWidth(); - // There might be negative interim results. - if (Addend.isUnsigned()) { - Addend = Addend.zext(++AddendBitWidth); - Addend.setIsSigned(true); - } - // Adjust the bit width of the APSInts. - if (AddendBitWidth > BitWidth) { - Offset = Offset.sext(AddendBitWidth); - BitWidth = AddendBitWidth; - } else if (BitWidth > AddendBitWidth) { - Addend = Addend.sext(BitWidth); - } - - bool Ov = false; - llvm::APSInt ResOffset = Offset; - if (BinOpKind == BO_Add) - ResOffset = Offset.sadd_ov(Addend, Ov); - else { - assert(AddendIsRight && BinOpKind == BO_Sub && - "operator must be add or sub with addend on the right"); - ResOffset = Offset.ssub_ov(Addend, Ov); - } - - // We add an offset to a pointer here so we should support an offset as big as - // possible. - if (Ov) { - assert(BitWidth <= UINT_MAX / 2 && "index (intermediate) result too big"); - Offset = Offset.sext(2 * BitWidth); - sumOffsets(Offset, Addend, BinOpKind, AddendIsRight); - return; - } - - Offset = ResOffset; } -namespace { -// This is a wrapper class around StringLiteral to support offsetted string -// literals as format strings. It takes the offset into account when returning -// the string and its length or the source locations to display notes correctly. -class FormatStringLiteral { - const StringLiteral *FExpr; - int64_t Offset; - - public: - FormatStringLiteral(const StringLiteral *fexpr, int64_t Offset = 0) - : FExpr(fexpr), Offset(Offset) {} - - StringRef getString() const { - return FExpr->getString().drop_front(Offset); - } - - unsigned getByteLength() const { - return FExpr->getByteLength() - getCharByteWidth() * Offset; - } - unsigned getLength() const { return FExpr->getLength() - Offset; } - unsigned getCharByteWidth() const { return FExpr->getCharByteWidth(); } - - StringLiteral::StringKind getKind() const { return FExpr->getKind(); } - - QualType getType() const { return FExpr->getType(); } - - bool isAscii() const { return FExpr->isAscii(); } - bool isWide() const { return FExpr->isWide(); } - bool isUTF8() const { return FExpr->isUTF8(); } - bool isUTF16() const { return FExpr->isUTF16(); } - bool isUTF32() const { return FExpr->isUTF32(); } - bool isPascal() const { return FExpr->isPascal(); } - - SourceLocation getLocationOfByte( - unsigned ByteNo, const SourceManager &SM, const LangOptions &Features, - const TargetInfo &Target, unsigned *StartToken = nullptr, - unsigned *StartTokenByteOffset = nullptr) const { - return FExpr->getLocationOfByte(ByteNo + Offset, SM, Features, Target, - StartToken, StartTokenByteOffset); - } - - SourceLocation getLocStart() const LLVM_READONLY { - return FExpr->getLocStart().getLocWithOffset(Offset); - } - SourceLocation getLocEnd() const LLVM_READONLY { return FExpr->getLocEnd(); } -}; -} // end anonymous namespace - -static void CheckFormatString(Sema &S, const FormatStringLiteral *FExpr, - const Expr *OrigFormatExpr, - ArrayRef<const Expr *> Args, - bool HasVAListArg, unsigned format_idx, - unsigned firstDataArg, - Sema::FormatStringType Type, - bool inFunctionCall, - Sema::VariadicCallType CallType, - llvm::SmallBitVector &CheckedVarArgs, - UncoveredArgHandler &UncoveredArg); - // Determine if an expression is a string literal or constant string. // If this function returns false on the arguments to a function expecting a // format string, we will usually need to emit a warning. @@ -4437,12 +3029,8 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args, bool HasVAListArg, unsigned format_idx, unsigned firstDataArg, Sema::FormatStringType Type, Sema::VariadicCallType CallType, bool InFunctionCall, - llvm::SmallBitVector &CheckedVarArgs, - UncoveredArgHandler &UncoveredArg, - llvm::APSInt Offset) { + llvm::SmallBitVector &CheckedVarArgs) { tryAgain: - assert(Offset.isSigned() && "invalid offset"); - if (E->isTypeDependent() || E->isValueDependent()) return SLCT_NotALiteral; @@ -4462,44 +3050,17 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args, // completely checked only if both sub-expressions were checked. const AbstractConditionalOperator *C = cast<AbstractConditionalOperator>(E); - - // Determine whether it is necessary to check both sub-expressions, for - // example, because the condition expression is a constant that can be - // evaluated at compile time. - bool CheckLeft = true, CheckRight = true; - - bool Cond; - if (C->getCond()->EvaluateAsBooleanCondition(Cond, S.getASTContext())) { - if (Cond) - CheckRight = false; - else - CheckLeft = false; - } - - // We need to maintain the offsets for the right and the left hand side - // separately to check if every possible indexed expression is a valid - // string literal. They might have different offsets for different string - // literals in the end. - StringLiteralCheckType Left; - if (!CheckLeft) - Left = SLCT_UncheckedLiteral; - else { - Left = checkFormatStringExpr(S, C->getTrueExpr(), Args, - HasVAListArg, format_idx, firstDataArg, - Type, CallType, InFunctionCall, - CheckedVarArgs, UncoveredArg, Offset); - if (Left == SLCT_NotALiteral || !CheckRight) { - return Left; - } - } - + StringLiteralCheckType Left = + checkFormatStringExpr(S, C->getTrueExpr(), Args, + HasVAListArg, format_idx, firstDataArg, + Type, CallType, InFunctionCall, CheckedVarArgs); + if (Left == SLCT_NotALiteral) + return SLCT_NotALiteral; StringLiteralCheckType Right = checkFormatStringExpr(S, C->getFalseExpr(), Args, HasVAListArg, format_idx, firstDataArg, - Type, CallType, InFunctionCall, CheckedVarArgs, - UncoveredArg, Offset); - - return (CheckLeft && Left < Right) ? Left : Right; + Type, CallType, InFunctionCall, CheckedVarArgs); + return Left < Right ? Left : Right; } case Stmt::ImplicitCastExprClass: { @@ -4550,8 +3111,7 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args, return checkFormatStringExpr(S, Init, Args, HasVAListArg, format_idx, firstDataArg, Type, CallType, - /*InFunctionCall*/ false, CheckedVarArgs, - UncoveredArg, Offset); + /*InFunctionCall*/false, CheckedVarArgs); } } @@ -4606,7 +3166,7 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args, return checkFormatStringExpr(S, Arg, Args, HasVAListArg, format_idx, firstDataArg, Type, CallType, InFunctionCall, - CheckedVarArgs, UncoveredArg, Offset); + CheckedVarArgs); } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) { unsigned BuiltinID = FD->getBuiltinID(); if (BuiltinID == Builtin::BI__builtin___CFStringMakeConstantString || @@ -4615,28 +3175,13 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args, return checkFormatStringExpr(S, Arg, Args, HasVAListArg, format_idx, firstDataArg, Type, CallType, - InFunctionCall, CheckedVarArgs, - UncoveredArg, Offset); + InFunctionCall, CheckedVarArgs); } } } return SLCT_NotALiteral; } - case Stmt::ObjCMessageExprClass: { - const auto *ME = cast<ObjCMessageExpr>(E); - if (const auto *ND = ME->getMethodDecl()) { - if (const auto *FA = ND->getAttr<FormatArgAttr>()) { - unsigned ArgIndex = FA->getFormatIdx(); - const Expr *Arg = ME->getArg(ArgIndex - 1); - return checkFormatStringExpr( - S, Arg, Args, HasVAListArg, format_idx, firstDataArg, Type, - CallType, InFunctionCall, CheckedVarArgs, UncoveredArg, Offset); - } - } - - return SLCT_NotALiteral; - } case Stmt::ObjCStringLiteralClass: case Stmt::StringLiteralClass: { const StringLiteral *StrE = nullptr; @@ -4647,64 +3192,13 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args, StrE = cast<StringLiteral>(E); if (StrE) { - if (Offset.isNegative() || Offset > StrE->getLength()) { - // TODO: It would be better to have an explicit warning for out of - // bounds literals. - return SLCT_NotALiteral; - } - FormatStringLiteral FStr(StrE, Offset.sextOrTrunc(64).getSExtValue()); - CheckFormatString(S, &FStr, E, Args, HasVAListArg, format_idx, - firstDataArg, Type, InFunctionCall, CallType, - CheckedVarArgs, UncoveredArg); + S.CheckFormatString(StrE, E, Args, HasVAListArg, format_idx, firstDataArg, + Type, InFunctionCall, CallType, CheckedVarArgs); return SLCT_CheckedLiteral; } return SLCT_NotALiteral; } - case Stmt::BinaryOperatorClass: { - llvm::APSInt LResult; - llvm::APSInt RResult; - - const BinaryOperator *BinOp = cast<BinaryOperator>(E); - - // A string literal + an int offset is still a string literal. - if (BinOp->isAdditiveOp()) { - bool LIsInt = BinOp->getLHS()->EvaluateAsInt(LResult, S.Context); - bool RIsInt = BinOp->getRHS()->EvaluateAsInt(RResult, S.Context); - - if (LIsInt != RIsInt) { - BinaryOperatorKind BinOpKind = BinOp->getOpcode(); - - if (LIsInt) { - if (BinOpKind == BO_Add) { - sumOffsets(Offset, LResult, BinOpKind, RIsInt); - E = BinOp->getRHS(); - goto tryAgain; - } - } else { - sumOffsets(Offset, RResult, BinOpKind, RIsInt); - E = BinOp->getLHS(); - goto tryAgain; - } - } - } - - return SLCT_NotALiteral; - } - case Stmt::UnaryOperatorClass: { - const UnaryOperator *UnaOp = cast<UnaryOperator>(E); - auto ASE = dyn_cast<ArraySubscriptExpr>(UnaOp->getSubExpr()); - if (UnaOp->getOpcode() == clang::UO_AddrOf && ASE) { - llvm::APSInt IndexResult; - if (ASE->getRHS()->EvaluateAsInt(IndexResult, S.Context)) { - sumOffsets(Offset, IndexResult, BO_Add, /*RHS is int*/ true); - E = ASE->getBase(); - goto tryAgain; - } - } - - return SLCT_NotALiteral; - } default: return SLCT_NotALiteral; @@ -4713,16 +3207,15 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args, Sema::FormatStringType Sema::GetFormatStringType(const FormatAttr *Format) { return llvm::StringSwitch<FormatStringType>(Format->getType()->getName()) - .Case("scanf", FST_Scanf) - .Cases("printf", "printf0", FST_Printf) - .Cases("NSString", "CFString", FST_NSString) - .Case("strftime", FST_Strftime) - .Case("strfmon", FST_Strfmon) - .Cases("kprintf", "cmn_err", "vcmn_err", "zcmn_err", FST_Kprintf) - .Case("freebsd_kprintf", FST_FreeBSDKPrintf) - .Case("os_trace", FST_OSLog) - .Case("os_log", FST_OSLog) - .Default(FST_Unknown); + .Case("scanf", FST_Scanf) + .Cases("printf", "printf0", FST_Printf) + .Cases("NSString", "CFString", FST_NSString) + .Case("strftime", FST_Strftime) + .Case("strfmon", FST_Strfmon) + .Cases("kprintf", "cmn_err", "vcmn_err", "zcmn_err", FST_Kprintf) + .Case("freebsd_kprintf", FST_FreeBSDKPrintf) + .Case("os_trace", FST_OSTrace) + .Default(FST_Unknown); } /// CheckFormatArguments - Check calls to printf and scanf (and similar @@ -4768,21 +3261,10 @@ bool Sema::CheckFormatArguments(ArrayRef<const Expr *> Args, // C string (e.g. "%d") // ObjC string uses the same format specifiers as C string, so we can use // the same format string checking logic for both ObjC and C strings. - UncoveredArgHandler UncoveredArg; StringLiteralCheckType CT = checkFormatStringExpr(*this, OrigFormatExpr, Args, HasVAListArg, format_idx, firstDataArg, Type, CallType, - /*IsFunctionCall*/ true, CheckedVarArgs, - UncoveredArg, - /*no string offset*/ llvm::APSInt(64, false) = 0); - - // Generate a diagnostic where an uncovered argument is detected. - if (UncoveredArg.hasUncoveredArg()) { - unsigned ArgIdx = UncoveredArg.getUncoveredArg() + firstDataArg; - assert(ArgIdx < Args.size() && "ArgIdx outside bounds"); - UncoveredArg.Diagnose(*this, /*IsFunctionCall*/true, Args[ArgIdx]); - } - + /*IsFunctionCall*/true, CheckedVarArgs); if (CT != SLCT_NotALiteral) // Literal format string found, check done! return CT == SLCT_CheckedLiteral; @@ -4796,33 +3278,20 @@ bool Sema::CheckFormatArguments(ArrayRef<const Expr *> Args, // format is either NSString or CFString. This is a hack to prevent // diag when using the NSLocalizedString and CFCopyLocalizedString macros // which are usually used in place of NS and CF string literals. - SourceLocation FormatLoc = Args[format_idx]->getLocStart(); - if (Type == FST_NSString && SourceMgr.isInSystemMacro(FormatLoc)) + if (Type == FST_NSString && + SourceMgr.isInSystemMacro(Args[format_idx]->getLocStart())) return false; // If there are no arguments specified, warn with -Wformat-security, otherwise // warn only with -Wformat-nonliteral. - if (Args.size() == firstDataArg) { - Diag(FormatLoc, diag::warn_format_nonliteral_noargs) - << OrigFormatExpr->getSourceRange(); - switch (Type) { - default: - break; - case FST_Kprintf: - case FST_FreeBSDKPrintf: - case FST_Printf: - Diag(FormatLoc, diag::note_format_security_fixit) - << FixItHint::CreateInsertion(FormatLoc, "\"%s\", "); - break; - case FST_NSString: - Diag(FormatLoc, diag::note_format_security_fixit) - << FixItHint::CreateInsertion(FormatLoc, "@\"%@\", "); - break; - } - } else { - Diag(FormatLoc, diag::warn_format_nonliteral) + if (Args.size() == firstDataArg) + Diag(Args[format_idx]->getLocStart(), + diag::warn_format_nonliteral_noargs) << OrigFormatExpr->getSourceRange(); - } + else + Diag(Args[format_idx]->getLocStart(), + diag::warn_format_nonliteral) + << OrigFormatExpr->getSourceRange(); return false; } @@ -4830,9 +3299,8 @@ namespace { class CheckFormatHandler : public analyze_format_string::FormatStringHandler { protected: Sema &S; - const FormatStringLiteral *FExpr; + const StringLiteral *FExpr; const Expr *OrigFormatExpr; - const Sema::FormatStringType FSType; const unsigned FirstDataArg; const unsigned NumDataArgs; const char *Beg; // Start of format string. @@ -4845,23 +3313,21 @@ protected: bool inFunctionCall; Sema::VariadicCallType CallType; llvm::SmallBitVector &CheckedVarArgs; - UncoveredArgHandler &UncoveredArg; - public: - CheckFormatHandler(Sema &s, const FormatStringLiteral *fexpr, - const Expr *origFormatExpr, - const Sema::FormatStringType type, unsigned firstDataArg, + CheckFormatHandler(Sema &s, const StringLiteral *fexpr, + const Expr *origFormatExpr, unsigned firstDataArg, unsigned numDataArgs, const char *beg, bool hasVAListArg, - ArrayRef<const Expr *> Args, unsigned formatIdx, - bool inFunctionCall, Sema::VariadicCallType callType, - llvm::SmallBitVector &CheckedVarArgs, - UncoveredArgHandler &UncoveredArg) - : S(s), FExpr(fexpr), OrigFormatExpr(origFormatExpr), FSType(type), - FirstDataArg(firstDataArg), NumDataArgs(numDataArgs), Beg(beg), - HasVAListArg(hasVAListArg), Args(Args), FormatIdx(formatIdx), - usesPositionalArgs(false), atFirstArg(true), - inFunctionCall(inFunctionCall), CallType(callType), - CheckedVarArgs(CheckedVarArgs), UncoveredArg(UncoveredArg) { + ArrayRef<const Expr *> Args, + unsigned formatIdx, bool inFunctionCall, + Sema::VariadicCallType callType, + llvm::SmallBitVector &CheckedVarArgs) + : S(s), FExpr(fexpr), OrigFormatExpr(origFormatExpr), + FirstDataArg(firstDataArg), NumDataArgs(numDataArgs), + Beg(beg), HasVAListArg(hasVAListArg), + Args(Args), FormatIdx(formatIdx), + usesPositionalArgs(false), atFirstArg(true), + inFunctionCall(inFunctionCall), CallType(callType), + CheckedVarArgs(CheckedVarArgs) { CoveredArgs.resize(numDataArgs); CoveredArgs.reset(); } @@ -4896,11 +3362,12 @@ public: void HandleNullChar(const char *nullCharacter) override; template <typename Range> - static void - EmitFormatDiagnostic(Sema &S, bool inFunctionCall, const Expr *ArgumentExpr, - const PartialDiagnostic &PDiag, SourceLocation StringLoc, - bool IsStringLocation, Range StringRange, - ArrayRef<FixItHint> Fixit = None); + static void EmitFormatDiagnostic(Sema &S, bool inFunctionCall, + const Expr *ArgumentExpr, + PartialDiagnostic PDiag, + SourceLocation StringLoc, + bool IsStringLocation, Range StringRange, + ArrayRef<FixItHint> Fixit = None); protected: bool HandleInvalidConversionSpecifier(unsigned argIndex, SourceLocation Loc, @@ -4929,7 +3396,7 @@ protected: bool IsStringLocation, Range StringRange, ArrayRef<FixItHint> Fixit = None); }; -} // end anonymous namespace +} SourceRange CheckFormatHandler::getFormatStringRange() { return OrigFormatExpr->getSourceRange(); @@ -4947,8 +3414,7 @@ getSpecifierRange(const char *startSpecifier, unsigned specifierLen) { } SourceLocation CheckFormatHandler::getLocationOfByte(const char *x) { - return FExpr->getLocationOfByte(x - Beg, S.getSourceManager(), - S.getLangOpts(), S.Context.getTargetInfo()); + return S.getLocationOfStringLiteralByte(FExpr, x - Beg); } void CheckFormatHandler::HandleIncompleteSpecifier(const char *startSpecifier, @@ -5092,44 +3558,26 @@ const Expr *CheckFormatHandler::getDataArg(unsigned i) const { } void CheckFormatHandler::DoneProcessing() { - // Does the number of data arguments exceed the number of - // format conversions in the format string? + // Does the number of data arguments exceed the number of + // format conversions in the format string? if (!HasVAListArg) { // Find any arguments that weren't covered. CoveredArgs.flip(); signed notCoveredArg = CoveredArgs.find_first(); if (notCoveredArg >= 0) { assert((unsigned)notCoveredArg < NumDataArgs); - UncoveredArg.Update(notCoveredArg, OrigFormatExpr); - } else { - UncoveredArg.setAllCovered(); + if (const Expr *E = getDataArg((unsigned) notCoveredArg)) { + SourceLocation Loc = E->getLocStart(); + if (!S.getSourceManager().isInSystemMacro(Loc)) { + EmitFormatDiagnostic(S.PDiag(diag::warn_printf_data_arg_not_used), + Loc, /*IsStringLocation*/false, + getFormatStringRange()); + } + } } } } -void UncoveredArgHandler::Diagnose(Sema &S, bool IsFunctionCall, - const Expr *ArgExpr) { - assert(hasUncoveredArg() && DiagnosticExprs.size() > 0 && - "Invalid state"); - - if (!ArgExpr) - return; - - SourceLocation Loc = ArgExpr->getLocStart(); - - if (S.getSourceManager().isInSystemMacro(Loc)) - return; - - PartialDiagnostic PDiag = S.PDiag(diag::warn_printf_data_arg_not_used); - for (auto E : DiagnosticExprs) - PDiag << E->getSourceRange(); - - CheckFormatHandler::EmitFormatDiagnostic( - S, IsFunctionCall, DiagnosticExprs[0], - PDiag, Loc, /*IsStringLocation*/false, - DiagnosticExprs[0]->getSourceRange()); -} - bool CheckFormatHandler::HandleInvalidConversionSpecifier(unsigned argIndex, SourceLocation Loc, @@ -5137,6 +3585,7 @@ CheckFormatHandler::HandleInvalidConversionSpecifier(unsigned argIndex, unsigned specifierLen, const char *csStart, unsigned csLen) { + bool keepGoing = true; if (argIndex < NumDataArgs) { // Consider the argument coverered, even though the specifier doesn't @@ -5151,41 +3600,12 @@ CheckFormatHandler::HandleInvalidConversionSpecifier(unsigned argIndex, // gibberish when trying to match arguments. keepGoing = false; } - - StringRef Specifier(csStart, csLen); - - // If the specifier in non-printable, it could be the first byte of a UTF-8 - // sequence. In that case, print the UTF-8 code point. If not, print the byte - // hex value. - std::string CodePointStr; - if (!llvm::sys::locale::isPrint(*csStart)) { - llvm::UTF32 CodePoint; - const llvm::UTF8 **B = reinterpret_cast<const llvm::UTF8 **>(&csStart); - const llvm::UTF8 *E = - reinterpret_cast<const llvm::UTF8 *>(csStart + csLen); - llvm::ConversionResult Result = - llvm::convertUTF8Sequence(B, E, &CodePoint, llvm::strictConversion); - - if (Result != llvm::conversionOK) { - unsigned char FirstChar = *csStart; - CodePoint = (llvm::UTF32)FirstChar; - } - - llvm::raw_string_ostream OS(CodePointStr); - if (CodePoint < 256) - OS << "\\x" << llvm::format("%02x", CodePoint); - else if (CodePoint <= 0xFFFF) - OS << "\\u" << llvm::format("%04x", CodePoint); - else - OS << "\\U" << llvm::format("%08x", CodePoint); - OS.flush(); - Specifier = CodePointStr; - } - - EmitFormatDiagnostic( - S.PDiag(diag::warn_format_invalid_conversion) << Specifier, Loc, - /*IsStringLocation*/ true, getSpecifierRange(startSpec, specifierLen)); - + + EmitFormatDiagnostic(S.PDiag(diag::warn_format_invalid_conversion) + << StringRef(csStart, csLen), + Loc, /*IsStringLocation*/true, + getSpecifierRange(startSpec, specifierLen)); + return keepGoing; } @@ -5212,10 +3632,6 @@ CheckFormatHandler::CheckNumArgs( EmitFormatDiagnostic( PDiag, getLocationOfByte(CS.getStart()), /*IsStringLocation*/true, getSpecifierRange(startSpecifier, specifierLen)); - - // Since more arguments than conversion tokens are given, by extension - // all arguments are covered, so mark this as so. - UncoveredArg.setAllCovered(); return false; } return true; @@ -5258,11 +3674,14 @@ void CheckFormatHandler::EmitFormatDiagnostic(PartialDiagnostic PDiag, /// templated so it can accept either a CharSourceRange or a SourceRange. /// /// \param FixIt optional fix it hint for the format string. -template <typename Range> -void CheckFormatHandler::EmitFormatDiagnostic( - Sema &S, bool InFunctionCall, const Expr *ArgumentExpr, - const PartialDiagnostic &PDiag, SourceLocation Loc, bool IsStringLocation, - Range StringRange, ArrayRef<FixItHint> FixIt) { +template<typename Range> +void CheckFormatHandler::EmitFormatDiagnostic(Sema &S, bool InFunctionCall, + const Expr *ArgumentExpr, + PartialDiagnostic PDiag, + SourceLocation Loc, + bool IsStringLocation, + Range StringRange, + ArrayRef<FixItHint> FixIt) { if (InFunctionCall) { const Sema::SemaDiagnosticBuilder &D = S.Diag(Loc, PDiag); D << StringRange; @@ -5284,28 +3703,22 @@ void CheckFormatHandler::EmitFormatDiagnostic( namespace { class CheckPrintfHandler : public CheckFormatHandler { + bool ObjCContext; public: - CheckPrintfHandler(Sema &s, const FormatStringLiteral *fexpr, - const Expr *origFormatExpr, - const Sema::FormatStringType type, unsigned firstDataArg, - unsigned numDataArgs, bool isObjC, const char *beg, - bool hasVAListArg, ArrayRef<const Expr *> Args, + CheckPrintfHandler(Sema &s, const StringLiteral *fexpr, + const Expr *origFormatExpr, unsigned firstDataArg, + unsigned numDataArgs, bool isObjC, + const char *beg, bool hasVAListArg, + ArrayRef<const Expr *> Args, unsigned formatIdx, bool inFunctionCall, Sema::VariadicCallType CallType, - llvm::SmallBitVector &CheckedVarArgs, - UncoveredArgHandler &UncoveredArg) - : CheckFormatHandler(s, fexpr, origFormatExpr, type, firstDataArg, - numDataArgs, beg, hasVAListArg, Args, formatIdx, - inFunctionCall, CallType, CheckedVarArgs, - UncoveredArg) {} - - bool isObjCContext() const { return FSType == Sema::FST_NSString; } + llvm::SmallBitVector &CheckedVarArgs) + : CheckFormatHandler(s, fexpr, origFormatExpr, firstDataArg, + numDataArgs, beg, hasVAListArg, Args, + formatIdx, inFunctionCall, CallType, CheckedVarArgs), + ObjCContext(isObjC) + {} - /// Returns true if '%@' specifiers are allowed in the format string. - bool allowsObjCArg() const { - return FSType == Sema::FST_NSString || FSType == Sema::FST_OSLog || - FSType == Sema::FST_OSTrace; - } bool HandleInvalidPrintfConversionSpecifier( const analyze_printf::PrintfSpecifier &FS, @@ -5347,7 +3760,7 @@ public: const char *conversionPosition) override; }; -} // end anonymous namespace +} bool CheckPrintfHandler::HandleInvalidPrintfConversionSpecifier( const analyze_printf::PrintfSpecifier &FS, @@ -5366,6 +3779,7 @@ bool CheckPrintfHandler::HandleAmount( const analyze_format_string::OptionalAmount &Amt, unsigned k, const char *startSpecifier, unsigned specifierLen) { + if (Amt.hasDataArgument()) { if (!HasVAListArg) { unsigned argIndex = Amt.getArgIndex(); @@ -5577,6 +3991,7 @@ CheckPrintfHandler::HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS, const char *startSpecifier, unsigned specifierLen) { + using namespace analyze_format_string; using namespace analyze_printf; const PrintfConversionSpecifier &CS = FS.getConversionSpecifier(); @@ -5659,54 +4074,11 @@ CheckPrintfHandler::HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier // Check for using an Objective-C specific conversion specifier // in a non-ObjC literal. - if (!allowsObjCArg() && CS.isObjCArg()) { - return HandleInvalidPrintfConversionSpecifier(FS, startSpecifier, - specifierLen); - } - - // %P can only be used with os_log. - if (FSType != Sema::FST_OSLog && CS.getKind() == ConversionSpecifier::PArg) { + if (!ObjCContext && CS.isObjCArg()) { return HandleInvalidPrintfConversionSpecifier(FS, startSpecifier, specifierLen); } - // %n is not allowed with os_log. - if (FSType == Sema::FST_OSLog && CS.getKind() == ConversionSpecifier::nArg) { - EmitFormatDiagnostic(S.PDiag(diag::warn_os_log_format_narg), - getLocationOfByte(CS.getStart()), - /*IsStringLocation*/ false, - getSpecifierRange(startSpecifier, specifierLen)); - - return true; - } - - // Only scalars are allowed for os_trace. - if (FSType == Sema::FST_OSTrace && - (CS.getKind() == ConversionSpecifier::PArg || - CS.getKind() == ConversionSpecifier::sArg || - CS.getKind() == ConversionSpecifier::ObjCObjArg)) { - return HandleInvalidPrintfConversionSpecifier(FS, startSpecifier, - specifierLen); - } - - // Check for use of public/private annotation outside of os_log(). - if (FSType != Sema::FST_OSLog) { - if (FS.isPublic().isSet()) { - EmitFormatDiagnostic(S.PDiag(diag::warn_format_invalid_annotation) - << "public", - getLocationOfByte(FS.isPublic().getPosition()), - /*IsStringLocation*/ false, - getSpecifierRange(startSpecifier, specifierLen)); - } - if (FS.isPrivate().isSet()) { - EmitFormatDiagnostic(S.PDiag(diag::warn_format_invalid_annotation) - << "private", - getLocationOfByte(FS.isPrivate().getPosition()), - /*IsStringLocation*/ false, - getSpecifierRange(startSpecifier, specifierLen)); - } - } - // Check for invalid use of field width if (!FS.hasValidFieldWidth()) { HandleInvalidAmount(FS, FS.getFieldWidth(), /* field width */ 0, @@ -5719,15 +4091,6 @@ CheckPrintfHandler::HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier startSpecifier, specifierLen); } - // Precision is mandatory for %P specifier. - if (CS.getKind() == ConversionSpecifier::PArg && - FS.getPrecision().getHowSpecified() == OptionalAmount::NotSpecified) { - EmitFormatDiagnostic(S.PDiag(diag::warn_format_P_no_precision), - getLocationOfByte(startSpecifier), - /*IsStringLocation*/ false, - getSpecifierRange(startSpecifier, specifierLen)); - } - // Check each flag does not conflict with any other component. if (!FS.hasValidThousandsGroupingPrefix()) HandleFlag(FS, FS.hasThousandsGrouping(), startSpecifier, specifierLen); @@ -5877,7 +4240,8 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, using namespace analyze_printf; // Now type check the data expression that matches the // format specifier. - const analyze_printf::ArgType &AT = FS.getArgType(S.Context, isObjCContext()); + const analyze_printf::ArgType &AT = FS.getArgType(S.Context, + ObjCContext); if (!AT.isValid()) return true; @@ -5932,7 +4296,7 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, // If the argument is an integer of some kind, believe the %C and suggest // a cast instead of changing the conversion specifier. QualType IntendedTy = ExprTy; - if (isObjCContext() && + if (ObjCContext && FS.getConversionSpecifier().getKind() == ConversionSpecifier::CArg) { if (ExprTy->isIntegralOrUnscopedEnumerationType() && !ExprTy->isCharType()) { @@ -5973,8 +4337,8 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, // We may be able to offer a FixItHint if it is a supported type. PrintfSpecifier fixedFS = FS; - bool success = - fixedFS.fixType(IntendedTy, S.getLangOpts(), S.Context, isObjCContext()); + bool success = fixedFS.fixType(IntendedTy, S.getLangOpts(), + S.Context, ObjCContext); if (success) { // Get the fix string from the fixed format specifier @@ -5997,6 +4361,7 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, E->getLocStart(), /*IsStringLocation*/ false, SpecRange, FixItHint::CreateReplacement(SpecRange, os.str())); + } else { // The canonical type for formatting this value is different from the // actual type of the expression. (This occurs, for example, with Darwin's @@ -6129,19 +4494,19 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, namespace { class CheckScanfHandler : public CheckFormatHandler { public: - CheckScanfHandler(Sema &s, const FormatStringLiteral *fexpr, - const Expr *origFormatExpr, Sema::FormatStringType type, - unsigned firstDataArg, unsigned numDataArgs, - const char *beg, bool hasVAListArg, - ArrayRef<const Expr *> Args, unsigned formatIdx, - bool inFunctionCall, Sema::VariadicCallType CallType, - llvm::SmallBitVector &CheckedVarArgs, - UncoveredArgHandler &UncoveredArg) - : CheckFormatHandler(s, fexpr, origFormatExpr, type, firstDataArg, - numDataArgs, beg, hasVAListArg, Args, formatIdx, - inFunctionCall, CallType, CheckedVarArgs, - UncoveredArg) {} - + CheckScanfHandler(Sema &s, const StringLiteral *fexpr, + const Expr *origFormatExpr, unsigned firstDataArg, + unsigned numDataArgs, const char *beg, bool hasVAListArg, + ArrayRef<const Expr *> Args, + unsigned formatIdx, bool inFunctionCall, + Sema::VariadicCallType CallType, + llvm::SmallBitVector &CheckedVarArgs) + : CheckFormatHandler(s, fexpr, origFormatExpr, firstDataArg, + numDataArgs, beg, hasVAListArg, + Args, formatIdx, inFunctionCall, CallType, + CheckedVarArgs) + {} + bool HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier &FS, const char *startSpecifier, unsigned specifierLen) override; @@ -6153,7 +4518,7 @@ public: void HandleIncompleteScanList(const char *start, const char *end) override; }; -} // end anonymous namespace +} void CheckScanfHandler::HandleIncompleteScanList(const char *start, const char *end) { @@ -6180,6 +4545,7 @@ bool CheckScanfHandler::HandleScanfSpecifier( const analyze_scanf::ScanfSpecifier &FS, const char *startSpecifier, unsigned specifierLen) { + using namespace analyze_scanf; using namespace analyze_format_string; @@ -6299,31 +4665,28 @@ bool CheckScanfHandler::HandleScanfSpecifier( return true; } -static void CheckFormatString(Sema &S, const FormatStringLiteral *FExpr, - const Expr *OrigFormatExpr, - ArrayRef<const Expr *> Args, - bool HasVAListArg, unsigned format_idx, - unsigned firstDataArg, - Sema::FormatStringType Type, - bool inFunctionCall, - Sema::VariadicCallType CallType, - llvm::SmallBitVector &CheckedVarArgs, - UncoveredArgHandler &UncoveredArg) { +void Sema::CheckFormatString(const StringLiteral *FExpr, + const Expr *OrigFormatExpr, + ArrayRef<const Expr *> Args, + bool HasVAListArg, unsigned format_idx, + unsigned firstDataArg, FormatStringType Type, + bool inFunctionCall, VariadicCallType CallType, + llvm::SmallBitVector &CheckedVarArgs) { + // CHECK: is the format string a wide literal? if (!FExpr->isAscii() && !FExpr->isUTF8()) { CheckFormatHandler::EmitFormatDiagnostic( - S, inFunctionCall, Args[format_idx], - S.PDiag(diag::warn_format_string_is_wide_literal), FExpr->getLocStart(), + *this, inFunctionCall, Args[format_idx], + PDiag(diag::warn_format_string_is_wide_literal), FExpr->getLocStart(), /*IsStringLocation*/true, OrigFormatExpr->getSourceRange()); return; } - + // Str - The format string. NOTE: this is NOT null-terminated! StringRef StrRef = FExpr->getString(); const char *Str = StrRef.data(); // Account for cases where the string literal is truncated in a declaration. - const ConstantArrayType *T = - S.Context.getAsConstantArrayType(FExpr->getType()); + const ConstantArrayType *T = Context.getAsConstantArrayType(FExpr->getType()); assert(T && "String literal not of constant array type!"); size_t TypeSize = T->getSize().getZExtValue(); size_t StrLen = std::min(std::max(TypeSize, size_t(1)) - 1, StrRef.size()); @@ -6334,8 +4697,8 @@ static void CheckFormatString(Sema &S, const FormatStringLiteral *FExpr, if (TypeSize <= StrRef.size() && StrRef.substr(0, TypeSize).find('\0') == StringRef::npos) { CheckFormatHandler::EmitFormatDiagnostic( - S, inFunctionCall, Args[format_idx], - S.PDiag(diag::warn_printf_format_string_not_null_terminated), + *this, inFunctionCall, Args[format_idx], + PDiag(diag::warn_printf_format_string_not_null_terminated), FExpr->getLocStart(), /*IsStringLocation=*/true, OrigFormatExpr->getSourceRange()); return; @@ -6344,34 +4707,32 @@ static void CheckFormatString(Sema &S, const FormatStringLiteral *FExpr, // CHECK: empty format string? if (StrLen == 0 && numDataArgs > 0) { CheckFormatHandler::EmitFormatDiagnostic( - S, inFunctionCall, Args[format_idx], - S.PDiag(diag::warn_empty_format_string), FExpr->getLocStart(), + *this, inFunctionCall, Args[format_idx], + PDiag(diag::warn_empty_format_string), FExpr->getLocStart(), /*IsStringLocation*/true, OrigFormatExpr->getSourceRange()); return; } - - if (Type == Sema::FST_Printf || Type == Sema::FST_NSString || - Type == Sema::FST_FreeBSDKPrintf || Type == Sema::FST_OSLog || - Type == Sema::FST_OSTrace) { - CheckPrintfHandler H( - S, FExpr, OrigFormatExpr, Type, firstDataArg, numDataArgs, - (Type == Sema::FST_NSString || Type == Sema::FST_OSTrace), Str, - HasVAListArg, Args, format_idx, inFunctionCall, CallType, - CheckedVarArgs, UncoveredArg); - + + if (Type == FST_Printf || Type == FST_NSString || + Type == FST_FreeBSDKPrintf || Type == FST_OSTrace) { + CheckPrintfHandler H(*this, FExpr, OrigFormatExpr, firstDataArg, + numDataArgs, (Type == FST_NSString || Type == FST_OSTrace), + Str, HasVAListArg, Args, format_idx, + inFunctionCall, CallType, CheckedVarArgs); + if (!analyze_format_string::ParsePrintfString(H, Str, Str + StrLen, - S.getLangOpts(), - S.Context.getTargetInfo(), - Type == Sema::FST_FreeBSDKPrintf)) + getLangOpts(), + Context.getTargetInfo(), + Type == FST_FreeBSDKPrintf)) H.DoneProcessing(); - } else if (Type == Sema::FST_Scanf) { - CheckScanfHandler H(S, FExpr, OrigFormatExpr, Type, firstDataArg, - numDataArgs, Str, HasVAListArg, Args, format_idx, - inFunctionCall, CallType, CheckedVarArgs, UncoveredArg); - + } else if (Type == FST_Scanf) { + CheckScanfHandler H(*this, FExpr, OrigFormatExpr, firstDataArg, numDataArgs, + Str, HasVAListArg, Args, format_idx, + inFunctionCall, CallType, CheckedVarArgs); + if (!analyze_format_string::ParseScanfString(H, Str, Str + StrLen, - S.getLangOpts(), - S.Context.getTargetInfo())) + getLangOpts(), + Context.getTargetInfo())) H.DoneProcessing(); } // TODO: handle other formats } @@ -6683,14 +5044,23 @@ static void emitReplacement(Sema &S, SourceLocation Loc, SourceRange Range, << FunctionName; } -template <std::size_t StrLen> -static bool IsStdFunction(const FunctionDecl *FDecl, - const char (&Str)[StrLen]) { +static bool IsFunctionStdAbs(const FunctionDecl *FDecl) { if (!FDecl) return false; - if (!FDecl->getIdentifier() || !FDecl->getIdentifier()->isStr(Str)) + + if (!FDecl->getIdentifier() || !FDecl->getIdentifier()->isStr("abs")) + return false; + + const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(FDecl->getDeclContext()); + + while (ND && ND->isInlineNamespace()) { + ND = dyn_cast<NamespaceDecl>(ND->getDeclContext()); + } + + if (!ND || !ND->getIdentifier() || !ND->getIdentifier()->isStr("std")) return false; - if (!FDecl->isInStdNamespace()) + + if (!isa<TranslationUnitDecl>(ND->getDeclContext())) return false; return true; @@ -6698,12 +5068,13 @@ static bool IsStdFunction(const FunctionDecl *FDecl, // Warn when using the wrong abs() function. void Sema::CheckAbsoluteValueFunction(const CallExpr *Call, - const FunctionDecl *FDecl) { + const FunctionDecl *FDecl, + IdentifierInfo *FnInfo) { if (Call->getNumArgs() != 1) return; unsigned AbsKind = getAbsoluteValueFunctionKind(FDecl); - bool IsStdAbs = IsStdFunction(FDecl, "abs"); + bool IsStdAbs = IsFunctionStdAbs(FDecl); if (AbsKind == 0 && !IsStdAbs) return; @@ -6774,69 +5145,7 @@ void Sema::CheckAbsoluteValueFunction(const CallExpr *Call, emitReplacement(*this, Call->getExprLoc(), Call->getCallee()->getSourceRange(), NewAbsKind, ArgType); -} - -//===--- CHECK: Warn on use of std::max and unsigned zero. r---------------===// -void Sema::CheckMaxUnsignedZero(const CallExpr *Call, - const FunctionDecl *FDecl) { - if (!Call || !FDecl) return; - - // Ignore template specializations and macros. - if (!ActiveTemplateInstantiations.empty()) return; - if (Call->getExprLoc().isMacroID()) return; - - // Only care about the one template argument, two function parameter std::max - if (Call->getNumArgs() != 2) return; - if (!IsStdFunction(FDecl, "max")) return; - const auto * ArgList = FDecl->getTemplateSpecializationArgs(); - if (!ArgList) return; - if (ArgList->size() != 1) return; - - // Check that template type argument is unsigned integer. - const auto& TA = ArgList->get(0); - if (TA.getKind() != TemplateArgument::Type) return; - QualType ArgType = TA.getAsType(); - if (!ArgType->isUnsignedIntegerType()) return; - - // See if either argument is a literal zero. - auto IsLiteralZeroArg = [](const Expr* E) -> bool { - const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E); - if (!MTE) return false; - const auto *Num = dyn_cast<IntegerLiteral>(MTE->GetTemporaryExpr()); - if (!Num) return false; - if (Num->getValue() != 0) return false; - return true; - }; - - const Expr *FirstArg = Call->getArg(0); - const Expr *SecondArg = Call->getArg(1); - const bool IsFirstArgZero = IsLiteralZeroArg(FirstArg); - const bool IsSecondArgZero = IsLiteralZeroArg(SecondArg); - - // Only warn when exactly one argument is zero. - if (IsFirstArgZero == IsSecondArgZero) return; - - SourceRange FirstRange = FirstArg->getSourceRange(); - SourceRange SecondRange = SecondArg->getSourceRange(); - - SourceRange ZeroRange = IsFirstArgZero ? FirstRange : SecondRange; - - Diag(Call->getExprLoc(), diag::warn_max_unsigned_zero) - << IsFirstArgZero << Call->getCallee()->getSourceRange() << ZeroRange; - - // Deduce what parts to remove so that "std::max(0u, foo)" becomes "(foo)". - SourceRange RemovalRange; - if (IsFirstArgZero) { - RemovalRange = SourceRange(FirstRange.getBegin(), - SecondRange.getBegin().getLocWithOffset(-1)); - } else { - RemovalRange = SourceRange(getLocForEndOfToken(FirstRange.getEnd()), - SecondRange.getEnd()); - } - - Diag(Call->getExprLoc(), diag::note_remove_max_call) - << FixItHint::CreateRemoval(Call->getCallee()->getSourceRange()) - << FixItHint::CreateRemoval(RemovalRange); + return; } //===--- CHECK: Standard memory functions ---------------------------------===// @@ -6882,7 +5191,7 @@ static const CXXRecordDecl *getContainedDynamicClass(QualType T, const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl(); RD = RD ? RD->getDefinition() : nullptr; - if (!RD || RD->isInvalidDecl()) + if (!RD) return nullptr; if (RD->isDynamicClass()) @@ -6938,15 +5247,13 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call, // It is possible to have a non-standard definition of memset. Validate // we have enough arguments, and if not, abort further checking. - unsigned ExpectedNumArgs = - (BId == Builtin::BIstrndup || BId == Builtin::BIbzero ? 2 : 3); + unsigned ExpectedNumArgs = (BId == Builtin::BIstrndup ? 2 : 3); if (Call->getNumArgs() < ExpectedNumArgs) return; - unsigned LastArg = (BId == Builtin::BImemset || BId == Builtin::BIbzero || + unsigned LastArg = (BId == Builtin::BImemset || BId == Builtin::BIstrndup ? 1 : 2); - unsigned LenArg = - (BId == Builtin::BIbzero || BId == Builtin::BIstrndup ? 1 : 2); + unsigned LenArg = (BId == Builtin::BIstrndup ? 1 : 2); const Expr *LenExpr = Call->getArg(LenArg)->IgnoreParenImpCasts(); if (CheckMemorySizeofForComparison(*this, LenExpr, FnName, @@ -6958,13 +5265,6 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call, const Expr *SizeOfArg = getSizeOfExprArg(LenExpr); llvm::FoldingSetNodeID SizeOfArgID; - // Although widely used, 'bzero' is not a standard function. Be more strict - // with the argument types before allowing diagnostics and only allow the - // form bzero(ptr, sizeof(...)). - QualType FirstArgTy = Call->getArg(0)->IgnoreParenImpCasts()->getType(); - if (BId == Builtin::BIbzero && !FirstArgTy->getAs<PointerType>()) - return; - for (unsigned ArgIdx = 0; ArgIdx != LastArg; ++ArgIdx) { const Expr *Dest = Call->getArg(ArgIdx)->IgnoreParenImpCasts(); SourceRange ArgRange = Call->getArg(ArgIdx)->getSourceRange(); @@ -7098,6 +5398,7 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call, << FixItHint::CreateInsertion(ArgRange.getBegin(), "(void*)")); break; } + } // A little helper routine: ignore addition and subtraction of integer literals. @@ -7312,12 +5613,10 @@ void Sema::CheckStrncatArguments(const CallExpr *CE, //===--- CHECK: Return Address of Stack Variable --------------------------===// -static const Expr *EvalVal(const Expr *E, - SmallVectorImpl<const DeclRefExpr *> &refVars, - const Decl *ParentDecl); -static const Expr *EvalAddr(const Expr *E, - SmallVectorImpl<const DeclRefExpr *> &refVars, - const Decl *ParentDecl); +static Expr *EvalVal(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars, + Decl *ParentDecl); +static Expr *EvalAddr(Expr* E, SmallVectorImpl<DeclRefExpr *> &refVars, + Decl *ParentDecl); /// CheckReturnStackAddr - Check if a return statement returns the address /// of a stack variable. @@ -7325,8 +5624,8 @@ static void CheckReturnStackAddr(Sema &S, Expr *RetValExp, QualType lhsType, SourceLocation ReturnLoc) { - const Expr *stackE = nullptr; - SmallVector<const DeclRefExpr *, 8> refVars; + Expr *stackE = nullptr; + SmallVector<DeclRefExpr *, 8> refVars; // Perform checking for returned stack addresses, local blocks, // label addresses or references to temporaries. @@ -7340,12 +5639,6 @@ CheckReturnStackAddr(Sema &S, Expr *RetValExp, QualType lhsType, if (!stackE) return; // Nothing suspicious was found. - // Parameters are initalized in the calling scope, so taking the address - // of a parameter reference doesn't need a warning. - for (auto *DRE : refVars) - if (isa<ParmVarDecl>(DRE->getDecl())) - return; - SourceLocation diagLoc; SourceRange diagRange; if (refVars.empty()) { @@ -7360,8 +5653,7 @@ CheckReturnStackAddr(Sema &S, Expr *RetValExp, QualType lhsType, diagRange = refVars[0]->getSourceRange(); } - if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(stackE)) { - // address of local var + if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(stackE)) { //address of local var. S.Diag(diagLoc, diag::warn_ret_stack_addr_ref) << lhsType->isReferenceType() << DR->getDecl()->getDeclName() << diagRange; } else if (isa<BlockExpr>(stackE)) { // local block. @@ -7369,13 +5661,6 @@ CheckReturnStackAddr(Sema &S, Expr *RetValExp, QualType lhsType, } else if (isa<AddrLabelExpr>(stackE)) { // address of label. S.Diag(diagLoc, diag::warn_ret_addr_label) << diagRange; } else { // local temporary. - // If there is an LValue->RValue conversion, then the value of the - // reference type is used, not the reference. - if (auto *ICE = dyn_cast<ImplicitCastExpr>(RetValExp)) { - if (ICE->getCastKind() == CK_LValueToRValue) { - return; - } - } S.Diag(diagLoc, diag::warn_ret_local_temp_addr_ref) << lhsType->isReferenceType() << diagRange; } @@ -7383,12 +5668,12 @@ CheckReturnStackAddr(Sema &S, Expr *RetValExp, QualType lhsType, // Display the "trail" of reference variables that we followed until we // found the problematic expression using notes. for (unsigned i = 0, e = refVars.size(); i != e; ++i) { - const VarDecl *VD = cast<VarDecl>(refVars[i]->getDecl()); + VarDecl *VD = cast<VarDecl>(refVars[i]->getDecl()); // If this var binds to another reference var, show the range of the next // var, otherwise the var binds to the problematic expression, in which case // show the range of the expression. - SourceRange range = (i < e - 1) ? refVars[i + 1]->getSourceRange() - : stackE->getSourceRange(); + SourceRange range = (i < e-1) ? refVars[i+1]->getSourceRange() + : stackE->getSourceRange(); S.Diag(VD->getLocation(), diag::note_ref_var_local_bind) << VD->getDeclName() << range; } @@ -7420,9 +5705,8 @@ CheckReturnStackAddr(Sema &S, Expr *RetValExp, QualType lhsType, /// * arbitrary interplay between "&" and "*" operators /// * pointer arithmetic from an address of a stack variable /// * taking the address of an array element where the array is on the stack -static const Expr *EvalAddr(const Expr *E, - SmallVectorImpl<const DeclRefExpr *> &refVars, - const Decl *ParentDecl) { +static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars, + Decl *ParentDecl) { if (E->isTypeDependent()) return nullptr; @@ -7439,13 +5723,13 @@ static const Expr *EvalAddr(const Expr *E, // EvalAddr and EvalVal appropriately. switch (E->getStmtClass()) { case Stmt::DeclRefExprClass: { - const DeclRefExpr *DR = cast<DeclRefExpr>(E); + DeclRefExpr *DR = cast<DeclRefExpr>(E); // If we leave the immediate function, the lifetime isn't about to end. if (DR->refersToEnclosingVariableOrCapture()) return nullptr; - if (const VarDecl *V = dyn_cast<VarDecl>(DR->getDecl())) + if (VarDecl *V = dyn_cast<VarDecl>(DR->getDecl())) // If this is a reference variable, follow through to the expression that // it points to. if (V->hasLocalStorage() && @@ -7461,44 +5745,44 @@ static const Expr *EvalAddr(const Expr *E, case Stmt::UnaryOperatorClass: { // The only unary operator that make sense to handle here // is AddrOf. All others don't make sense as pointers. - const UnaryOperator *U = cast<UnaryOperator>(E); + UnaryOperator *U = cast<UnaryOperator>(E); if (U->getOpcode() == UO_AddrOf) return EvalVal(U->getSubExpr(), refVars, ParentDecl); - return nullptr; + else + return nullptr; } case Stmt::BinaryOperatorClass: { // Handle pointer arithmetic. All other binary operators are not valid // in this context. - const BinaryOperator *B = cast<BinaryOperator>(E); + BinaryOperator *B = cast<BinaryOperator>(E); BinaryOperatorKind op = B->getOpcode(); if (op != BO_Add && op != BO_Sub) return nullptr; - const Expr *Base = B->getLHS(); + Expr *Base = B->getLHS(); // Determine which argument is the real pointer base. It could be // the RHS argument instead of the LHS. - if (!Base->getType()->isPointerType()) - Base = B->getRHS(); + if (!Base->getType()->isPointerType()) Base = B->getRHS(); - assert(Base->getType()->isPointerType()); + assert (Base->getType()->isPointerType()); return EvalAddr(Base, refVars, ParentDecl); } // For conditional operators we need to see if either the LHS or RHS are // valid DeclRefExpr*s. If one of them is valid, we return it. case Stmt::ConditionalOperatorClass: { - const ConditionalOperator *C = cast<ConditionalOperator>(E); + ConditionalOperator *C = cast<ConditionalOperator>(E); // Handle the GNU extension for missing LHS. // FIXME: That isn't a ConditionalOperator, so doesn't get here. - if (const Expr *LHSExpr = C->getLHS()) { + if (Expr *LHSExpr = C->getLHS()) { // In C++, we can have a throw-expression, which has 'void' type. if (!LHSExpr->getType()->isVoidType()) - if (const Expr *LHS = EvalAddr(LHSExpr, refVars, ParentDecl)) + if (Expr *LHS = EvalAddr(LHSExpr, refVars, ParentDecl)) return LHS; } @@ -7531,7 +5815,7 @@ static const Expr *EvalAddr(const Expr *E, case Stmt::CXXDynamicCastExprClass: case Stmt::CXXConstCastExprClass: case Stmt::CXXReinterpretCastExprClass: { - const Expr* SubExpr = cast<CastExpr>(E)->getSubExpr(); + Expr* SubExpr = cast<CastExpr>(E)->getSubExpr(); switch (cast<CastExpr>(E)->getCastKind()) { case CK_LValueToRValue: case CK_NoOp: @@ -7561,161 +5845,157 @@ static const Expr *EvalAddr(const Expr *E, } case Stmt::MaterializeTemporaryExprClass: - if (const Expr *Result = - EvalAddr(cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr(), - refVars, ParentDecl)) + if (Expr *Result = EvalAddr( + cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr(), + refVars, ParentDecl)) return Result; + return E; - + // Everything else: we simply don't reason about them. default: return nullptr; } } + /// EvalVal - This function is complements EvalAddr in the mutual recursion. /// See the comments for EvalAddr for more details. -static const Expr *EvalVal(const Expr *E, - SmallVectorImpl<const DeclRefExpr *> &refVars, - const Decl *ParentDecl) { - do { - // We should only be called for evaluating non-pointer expressions, or - // expressions with a pointer type that are not used as references but - // instead - // are l-values (e.g., DeclRefExpr with a pointer type). - - // Our "symbolic interpreter" is just a dispatch off the currently - // viewed AST node. We then recursively traverse the AST by calling - // EvalAddr and EvalVal appropriately. - - E = E->IgnoreParens(); - switch (E->getStmtClass()) { - case Stmt::ImplicitCastExprClass: { - const ImplicitCastExpr *IE = cast<ImplicitCastExpr>(E); - if (IE->getValueKind() == VK_LValue) { - E = IE->getSubExpr(); - continue; - } - return nullptr; +static Expr *EvalVal(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars, + Decl *ParentDecl) { +do { + // We should only be called for evaluating non-pointer expressions, or + // expressions with a pointer type that are not used as references but instead + // are l-values (e.g., DeclRefExpr with a pointer type). + + // Our "symbolic interpreter" is just a dispatch off the currently + // viewed AST node. We then recursively traverse the AST by calling + // EvalAddr and EvalVal appropriately. + + E = E->IgnoreParens(); + switch (E->getStmtClass()) { + case Stmt::ImplicitCastExprClass: { + ImplicitCastExpr *IE = cast<ImplicitCastExpr>(E); + if (IE->getValueKind() == VK_LValue) { + E = IE->getSubExpr(); + continue; } + return nullptr; + } - case Stmt::ExprWithCleanupsClass: - return EvalVal(cast<ExprWithCleanups>(E)->getSubExpr(), refVars, - ParentDecl); + case Stmt::ExprWithCleanupsClass: + return EvalVal(cast<ExprWithCleanups>(E)->getSubExpr(), refVars,ParentDecl); - case Stmt::DeclRefExprClass: { - // When we hit a DeclRefExpr we are looking at code that refers to a - // variable's name. If it's not a reference variable we check if it has - // local storage within the function, and if so, return the expression. - const DeclRefExpr *DR = cast<DeclRefExpr>(E); + case Stmt::DeclRefExprClass: { + // When we hit a DeclRefExpr we are looking at code that refers to a + // variable's name. If it's not a reference variable we check if it has + // local storage within the function, and if so, return the expression. + DeclRefExpr *DR = cast<DeclRefExpr>(E); - // If we leave the immediate function, the lifetime isn't about to end. - if (DR->refersToEnclosingVariableOrCapture()) - return nullptr; + // If we leave the immediate function, the lifetime isn't about to end. + if (DR->refersToEnclosingVariableOrCapture()) + return nullptr; - if (const VarDecl *V = dyn_cast<VarDecl>(DR->getDecl())) { - // Check if it refers to itself, e.g. "int& i = i;". - if (V == ParentDecl) - return DR; + if (VarDecl *V = dyn_cast<VarDecl>(DR->getDecl())) { + // Check if it refers to itself, e.g. "int& i = i;". + if (V == ParentDecl) + return DR; - if (V->hasLocalStorage()) { - if (!V->getType()->isReferenceType()) - return DR; + if (V->hasLocalStorage()) { + if (!V->getType()->isReferenceType()) + return DR; - // Reference variable, follow through to the expression that - // it points to. - if (V->hasInit()) { - // Add the reference variable to the "trail". - refVars.push_back(DR); - return EvalVal(V->getInit(), refVars, V); - } + // Reference variable, follow through to the expression that + // it points to. + if (V->hasInit()) { + // Add the reference variable to the "trail". + refVars.push_back(DR); + return EvalVal(V->getInit(), refVars, V); } } - - return nullptr; } - case Stmt::UnaryOperatorClass: { - // The only unary operator that make sense to handle here - // is Deref. All others don't resolve to a "name." This includes - // handling all sorts of rvalues passed to a unary operator. - const UnaryOperator *U = cast<UnaryOperator>(E); + return nullptr; + } - if (U->getOpcode() == UO_Deref) - return EvalAddr(U->getSubExpr(), refVars, ParentDecl); + case Stmt::UnaryOperatorClass: { + // The only unary operator that make sense to handle here + // is Deref. All others don't resolve to a "name." This includes + // handling all sorts of rvalues passed to a unary operator. + UnaryOperator *U = cast<UnaryOperator>(E); - return nullptr; - } + if (U->getOpcode() == UO_Deref) + return EvalAddr(U->getSubExpr(), refVars, ParentDecl); - case Stmt::ArraySubscriptExprClass: { - // Array subscripts are potential references to data on the stack. We - // retrieve the DeclRefExpr* for the array variable if it indeed - // has local storage. - const auto *ASE = cast<ArraySubscriptExpr>(E); - if (ASE->isTypeDependent()) - return nullptr; - return EvalAddr(ASE->getBase(), refVars, ParentDecl); - } + return nullptr; + } - case Stmt::OMPArraySectionExprClass: { - return EvalAddr(cast<OMPArraySectionExpr>(E)->getBase(), refVars, - ParentDecl); - } + case Stmt::ArraySubscriptExprClass: { + // Array subscripts are potential references to data on the stack. We + // retrieve the DeclRefExpr* for the array variable if it indeed + // has local storage. + return EvalAddr(cast<ArraySubscriptExpr>(E)->getBase(), refVars,ParentDecl); + } - case Stmt::ConditionalOperatorClass: { - // For conditional operators we need to see if either the LHS or RHS are - // non-NULL Expr's. If one is non-NULL, we return it. - const ConditionalOperator *C = cast<ConditionalOperator>(E); - - // Handle the GNU extension for missing LHS. - if (const Expr *LHSExpr = C->getLHS()) { - // In C++, we can have a throw-expression, which has 'void' type. - if (!LHSExpr->getType()->isVoidType()) - if (const Expr *LHS = EvalVal(LHSExpr, refVars, ParentDecl)) - return LHS; - } + case Stmt::OMPArraySectionExprClass: { + return EvalAddr(cast<OMPArraySectionExpr>(E)->getBase(), refVars, + ParentDecl); + } - // In C++, we can have a throw-expression, which has 'void' type. - if (C->getRHS()->getType()->isVoidType()) - return nullptr; + case Stmt::ConditionalOperatorClass: { + // For conditional operators we need to see if either the LHS or RHS are + // non-NULL Expr's. If one is non-NULL, we return it. + ConditionalOperator *C = cast<ConditionalOperator>(E); - return EvalVal(C->getRHS(), refVars, ParentDecl); + // Handle the GNU extension for missing LHS. + if (Expr *LHSExpr = C->getLHS()) { + // In C++, we can have a throw-expression, which has 'void' type. + if (!LHSExpr->getType()->isVoidType()) + if (Expr *LHS = EvalVal(LHSExpr, refVars, ParentDecl)) + return LHS; } - // Accesses to members are potential references to data on the stack. - case Stmt::MemberExprClass: { - const MemberExpr *M = cast<MemberExpr>(E); + // In C++, we can have a throw-expression, which has 'void' type. + if (C->getRHS()->getType()->isVoidType()) + return nullptr; - // Check for indirect access. We only want direct field accesses. - if (M->isArrow()) - return nullptr; + return EvalVal(C->getRHS(), refVars, ParentDecl); + } - // Check whether the member type is itself a reference, in which case - // we're not going to refer to the member, but to what the member refers - // to. - if (M->getMemberDecl()->getType()->isReferenceType()) - return nullptr; + // Accesses to members are potential references to data on the stack. + case Stmt::MemberExprClass: { + MemberExpr *M = cast<MemberExpr>(E); - return EvalVal(M->getBase(), refVars, ParentDecl); - } + // Check for indirect access. We only want direct field accesses. + if (M->isArrow()) + return nullptr; - case Stmt::MaterializeTemporaryExprClass: - if (const Expr *Result = - EvalVal(cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr(), - refVars, ParentDecl)) - return Result; - return E; + // Check whether the member type is itself a reference, in which case + // we're not going to refer to the member, but to what the member refers to. + if (M->getMemberDecl()->getType()->isReferenceType()) + return nullptr; - default: - // Check that we don't return or take the address of a reference to a - // temporary. This is only useful in C++. - if (!E->isTypeDependent() && E->isRValue()) - return E; + return EvalVal(M->getBase(), refVars, ParentDecl); + } - // Everything else: we simply don't reason about them. - return nullptr; - } - } while (true); + case Stmt::MaterializeTemporaryExprClass: + if (Expr *Result = EvalVal( + cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr(), + refVars, ParentDecl)) + return Result; + + return E; + + default: + // Check that we don't return or take the address of a reference to a + // temporary. This is only useful in C++. + if (!E->isTypeDependent() && E->isRValue()) + return E; + + // Everything else: we simply don't reason about them. + return nullptr; + } +} while (true); } void @@ -7767,6 +6047,7 @@ void Sema::CheckFloatComparison(SourceLocation Loc, Expr* LHS, Expr *RHS) { if (DRL->getDecl() == DRR->getDecl()) return; + // Special case: check for comparisons against literals that can be exactly // represented by APFloat. In such cases, do not emit a warning. This // is a heuristic: often comparison against such literals are used to @@ -7892,7 +6173,8 @@ struct IntRange { } }; -IntRange GetValueRange(ASTContext &C, llvm::APSInt &value, unsigned MaxWidth) { +static IntRange GetValueRange(ASTContext &C, llvm::APSInt &value, + unsigned MaxWidth) { if (value.isSigned() && value.isNegative()) return IntRange(value.getMinSignedBits(), false); @@ -7904,8 +6186,8 @@ IntRange GetValueRange(ASTContext &C, llvm::APSInt &value, unsigned MaxWidth) { return IntRange(value.getActiveBits(), true); } -IntRange GetValueRange(ASTContext &C, APValue &result, QualType Ty, - unsigned MaxWidth) { +static IntRange GetValueRange(ASTContext &C, APValue &result, QualType Ty, + unsigned MaxWidth) { if (result.isInt()) return GetValueRange(C, result.getInt(), MaxWidth); @@ -7933,7 +6215,7 @@ IntRange GetValueRange(ASTContext &C, APValue &result, QualType Ty, return IntRange(MaxWidth, Ty->isUnsignedIntegerOrEnumerationType()); } -QualType GetExprType(const Expr *E) { +static QualType GetExprType(Expr *E) { QualType Ty = E->getType(); if (const AtomicType *AtomicRHS = Ty->getAs<AtomicType>()) Ty = AtomicRHS->getValueType(); @@ -7944,7 +6226,7 @@ QualType GetExprType(const Expr *E) { /// range of values it might take. /// /// \param MaxWidth - the width to which the value will be truncated -IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth) { +static IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) { E = E->IgnoreParens(); // Try a full evaluation first. @@ -7955,7 +6237,7 @@ IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth) { // I think we only want to look through implicit casts here; if the // user has an explicit widening cast, we should treat the value as // being of the new, wider type. - if (const auto *CE = dyn_cast<ImplicitCastExpr>(E)) { + if (ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(E)) { if (CE->getCastKind() == CK_NoOp || CE->getCastKind() == CK_LValueToRValue) return GetExprRange(C, CE->getSubExpr(), MaxWidth); @@ -7982,7 +6264,7 @@ IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth) { SubRange.NonNegative || OutputTypeRange.NonNegative); } - if (const auto *CO = dyn_cast<ConditionalOperator>(E)) { + if (ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E)) { // If we can fold the condition, just take that operand. bool CondResult; if (CO->getCond()->EvaluateAsBooleanCondition(CondResult, C)) @@ -7996,7 +6278,7 @@ IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth) { return IntRange::join(L, R); } - if (const auto *BO = dyn_cast<BinaryOperator>(E)) { + if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) { switch (BO->getOpcode()) { // Boolean-valued operations are single-bit and positive. @@ -8136,7 +6418,7 @@ IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth) { return IntRange::join(L, R); } - if (const auto *UO = dyn_cast<UnaryOperator>(E)) { + if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) { switch (UO->getOpcode()) { // Boolean-valued operations are white-listed. case UO_LNot: @@ -8152,26 +6434,26 @@ IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth) { } } - if (const auto *OVE = dyn_cast<OpaqueValueExpr>(E)) + if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E)) return GetExprRange(C, OVE->getSourceExpr(), MaxWidth); - if (const auto *BitField = E->getSourceBitField()) + if (FieldDecl *BitField = E->getSourceBitField()) return IntRange(BitField->getBitWidthValue(C), BitField->getType()->isUnsignedIntegerOrEnumerationType()); return IntRange::forValueOfType(C, GetExprType(E)); } -IntRange GetExprRange(ASTContext &C, const Expr *E) { +static IntRange GetExprRange(ASTContext &C, Expr *E) { return GetExprRange(C, E, C.getIntWidth(GetExprType(E))); } /// Checks whether the given value, which currently has the given /// source semantics, has the same value when coerced through the /// target semantics. -bool IsSameFloatAfterCast(const llvm::APFloat &value, - const llvm::fltSemantics &Src, - const llvm::fltSemantics &Tgt) { +static bool IsSameFloatAfterCast(const llvm::APFloat &value, + const llvm::fltSemantics &Src, + const llvm::fltSemantics &Tgt) { llvm::APFloat truncated = value; bool ignored; @@ -8186,9 +6468,9 @@ bool IsSameFloatAfterCast(const llvm::APFloat &value, /// target semantics. /// /// The value might be a vector of floats (or a complex number). -bool IsSameFloatAfterCast(const APValue &value, - const llvm::fltSemantics &Src, - const llvm::fltSemantics &Tgt) { +static bool IsSameFloatAfterCast(const APValue &value, + const llvm::fltSemantics &Src, + const llvm::fltSemantics &Tgt) { if (value.isFloat()) return IsSameFloatAfterCast(value.getFloat(), Src, Tgt); @@ -8204,9 +6486,9 @@ bool IsSameFloatAfterCast(const APValue &value, IsSameFloatAfterCast(value.getComplexFloatImag(), Src, Tgt)); } -void AnalyzeImplicitConversions(Sema &S, Expr *E, SourceLocation CC); +static void AnalyzeImplicitConversions(Sema &S, Expr *E, SourceLocation CC); -bool IsZero(Sema &S, Expr *E) { +static bool IsZero(Sema &S, Expr *E) { // Suppress cases where we are comparing against an enum constant. if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts())) @@ -8221,7 +6503,7 @@ bool IsZero(Sema &S, Expr *E) { return E->isIntegerConstantExpr(Value, S.Context) && Value == 0; } -bool HasEnumType(Expr *E) { +static bool HasEnumType(Expr *E) { // Strip off implicit integral promotions. while (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) { if (ICE->getCastKind() != CK_IntegralCast && @@ -8233,7 +6515,7 @@ bool HasEnumType(Expr *E) { return E->getType()->isEnumeralType(); } -void CheckTrivialUnsignedComparison(Sema &S, BinaryOperator *E) { +static void CheckTrivialUnsignedComparison(Sema &S, BinaryOperator *E) { // Disable warning in template instantiations. if (!S.ActiveTemplateInstantiations.empty()) return; @@ -8261,9 +6543,10 @@ void CheckTrivialUnsignedComparison(Sema &S, BinaryOperator *E) { } } -void DiagnoseOutOfRangeComparison(Sema &S, BinaryOperator *E, Expr *Constant, - Expr *Other, const llvm::APSInt &Value, - bool RhsConstant) { +static void DiagnoseOutOfRangeComparison(Sema &S, BinaryOperator *E, + Expr *Constant, Expr *Other, + llvm::APSInt Value, + bool RhsConstant) { // Disable warning in template instantiations. if (!S.ActiveTemplateInstantiations.empty()) return; @@ -8471,7 +6754,7 @@ void DiagnoseOutOfRangeComparison(Sema &S, BinaryOperator *E, Expr *Constant, /// Analyze the operands of the given comparison. Implements the /// fallback case from AnalyzeComparison. -void AnalyzeImpConvsInComparison(Sema &S, BinaryOperator *E) { +static void AnalyzeImpConvsInComparison(Sema &S, BinaryOperator *E) { AnalyzeImplicitConversions(S, E->getLHS(), E->getOperatorLoc()); AnalyzeImplicitConversions(S, E->getRHS(), E->getOperatorLoc()); } @@ -8479,7 +6762,7 @@ void AnalyzeImpConvsInComparison(Sema &S, BinaryOperator *E) { /// \brief Implements -Wsign-compare. /// /// \param E the binary operator to check for warnings -void AnalyzeComparison(Sema &S, BinaryOperator *E) { +static void AnalyzeComparison(Sema &S, BinaryOperator *E) { // The type the comparison is being performed in. QualType T = E->getLHS()->getType(); @@ -8580,31 +6863,13 @@ void AnalyzeComparison(Sema &S, BinaryOperator *E) { /// Analyzes an attempt to assign the given value to a bitfield. /// /// Returns true if there was something fishy about the attempt. -bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init, - SourceLocation InitLoc) { +static bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init, + SourceLocation InitLoc) { assert(Bitfield->isBitField()); if (Bitfield->isInvalidDecl()) return false; // White-list bool bitfields. - QualType BitfieldType = Bitfield->getType(); - if (BitfieldType->isBooleanType()) - return false; - - if (BitfieldType->isEnumeralType()) { - EnumDecl *BitfieldEnumDecl = BitfieldType->getAs<EnumType>()->getDecl(); - // If the underlying enum type was not explicitly specified as an unsigned - // type and the enum contain only positive values, MSVC++ will cause an - // inconsistency by storing this as a signed type. - if (S.getLangOpts().CPlusPlus11 && - !BitfieldEnumDecl->getIntegerTypeSourceInfo() && - BitfieldEnumDecl->getNumPositiveBits() > 0 && - BitfieldEnumDecl->getNumNegativeBits() == 0) { - S.Diag(InitLoc, diag::warn_no_underlying_type_specified_for_enum_bitfield) - << BitfieldEnumDecl->getNameAsString(); - } - } - if (Bitfield->getType()->isBooleanType()) return false; @@ -8624,17 +6889,12 @@ bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init, unsigned OriginalWidth = Value.getBitWidth(); unsigned FieldWidth = Bitfield->getBitWidthValue(S.Context); - if (!Value.isSigned() || Value.isNegative()) - if (UnaryOperator *UO = dyn_cast<UnaryOperator>(OriginalInit)) - if (UO->getOpcode() == UO_Minus || UO->getOpcode() == UO_Not) - OriginalWidth = Value.getMinSignedBits(); - if (OriginalWidth <= FieldWidth) return false; // Compute the value which the bitfield will contain. llvm::APSInt TruncatedValue = Value.trunc(FieldWidth); - TruncatedValue.setIsSigned(BitfieldType->isSignedIntegerType()); + TruncatedValue.setIsSigned(Bitfield->getType()->isSignedIntegerType()); // Check whether the stored value is equal to the original value. TruncatedValue = TruncatedValue.extend(OriginalWidth); @@ -8658,7 +6918,7 @@ bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init, /// Analyze the given simple or compound assignment for warning-worthy /// operations. -void AnalyzeAssignment(Sema &S, BinaryOperator *E) { +static void AnalyzeAssignment(Sema &S, BinaryOperator *E) { // Just recurse on the LHS. AnalyzeImplicitConversions(S, E->getLHS(), E->getOperatorLoc()); @@ -8677,9 +6937,9 @@ void AnalyzeAssignment(Sema &S, BinaryOperator *E) { } /// Diagnose an implicit cast; purely a helper for CheckImplicitConversion. -void DiagnoseImpCast(Sema &S, Expr *E, QualType SourceType, QualType T, - SourceLocation CContext, unsigned diag, - bool pruneControlFlow = false) { +static void DiagnoseImpCast(Sema &S, Expr *E, QualType SourceType, QualType T, + SourceLocation CContext, unsigned diag, + bool pruneControlFlow = false) { if (pruneControlFlow) { S.DiagRuntimeBehavior(E->getExprLoc(), E, S.PDiag(diag) @@ -8692,75 +6952,25 @@ void DiagnoseImpCast(Sema &S, Expr *E, QualType SourceType, QualType T, } /// Diagnose an implicit cast; purely a helper for CheckImplicitConversion. -void DiagnoseImpCast(Sema &S, Expr *E, QualType T, SourceLocation CContext, - unsigned diag, bool pruneControlFlow = false) { +static void DiagnoseImpCast(Sema &S, Expr *E, QualType T, + SourceLocation CContext, unsigned diag, + bool pruneControlFlow = false) { DiagnoseImpCast(S, E, E->getType(), T, CContext, diag, pruneControlFlow); } - -/// Diagnose an implicit cast from a floating point value to an integer value. -void DiagnoseFloatingImpCast(Sema &S, Expr *E, QualType T, - - SourceLocation CContext) { - const bool IsBool = T->isSpecificBuiltinType(BuiltinType::Bool); - const bool PruneWarnings = !S.ActiveTemplateInstantiations.empty(); - - Expr *InnerE = E->IgnoreParenImpCasts(); - // We also want to warn on, e.g., "int i = -1.234" - if (UnaryOperator *UOp = dyn_cast<UnaryOperator>(InnerE)) - if (UOp->getOpcode() == UO_Minus || UOp->getOpcode() == UO_Plus) - InnerE = UOp->getSubExpr()->IgnoreParenImpCasts(); - - const bool IsLiteral = - isa<FloatingLiteral>(E) || isa<FloatingLiteral>(InnerE); - - llvm::APFloat Value(0.0); - bool IsConstant = - E->EvaluateAsFloat(Value, S.Context, Expr::SE_AllowSideEffects); - if (!IsConstant) { - return DiagnoseImpCast(S, E, T, CContext, - diag::warn_impcast_float_integer, PruneWarnings); - } - +/// Diagnose an implicit cast from a literal expression. Does not warn when the +/// cast wouldn't lose information. +void DiagnoseFloatingLiteralImpCast(Sema &S, FloatingLiteral *FL, QualType T, + SourceLocation CContext) { + // Try to convert the literal exactly to an integer. If we can, don't warn. bool isExact = false; - + const llvm::APFloat &Value = FL->getValue(); llvm::APSInt IntegerValue(S.Context.getIntWidth(T), T->hasUnsignedIntegerRepresentation()); - if (Value.convertToInteger(IntegerValue, llvm::APFloat::rmTowardZero, - &isExact) == llvm::APFloat::opOK && - isExact) { - if (IsLiteral) return; - return DiagnoseImpCast(S, E, T, CContext, diag::warn_impcast_float_integer, - PruneWarnings); - } - - unsigned DiagID = 0; - if (IsLiteral) { - // Warn on floating point literal to integer. - DiagID = diag::warn_impcast_literal_float_to_integer; - } else if (IntegerValue == 0) { - if (Value.isZero()) { // Skip -0.0 to 0 conversion. - return DiagnoseImpCast(S, E, T, CContext, - diag::warn_impcast_float_integer, PruneWarnings); - } - // Warn on non-zero to zero conversion. - DiagID = diag::warn_impcast_float_to_integer_zero; - } else { - if (IntegerValue.isUnsigned()) { - if (!IntegerValue.isMaxValue()) { - return DiagnoseImpCast(S, E, T, CContext, - diag::warn_impcast_float_integer, PruneWarnings); - } - } else { // IntegerValue.isSigned() - if (!IntegerValue.isMaxSignedValue() && - !IntegerValue.isMinSignedValue()) { - return DiagnoseImpCast(S, E, T, CContext, - diag::warn_impcast_float_integer, PruneWarnings); - } - } - // Warn on evaluatable floating point expression to integer conversion. - DiagID = diag::warn_impcast_float_to_integer; - } + if (Value.convertToInteger(IntegerValue, + llvm::APFloat::rmTowardZero, &isExact) + == llvm::APFloat::opOK && isExact) + return; // FIXME: Force the precision of the source value down so we don't print // digits which are usually useless (we don't really care here if we @@ -8773,22 +6983,14 @@ void DiagnoseFloatingImpCast(Sema &S, Expr *E, QualType T, Value.toString(PrettySourceValue, precision); SmallString<16> PrettyTargetValue; - if (IsBool) + if (T->isSpecificBuiltinType(BuiltinType::Bool)) PrettyTargetValue = Value.isZero() ? "false" : "true"; else IntegerValue.toString(PrettyTargetValue); - if (PruneWarnings) { - S.DiagRuntimeBehavior(E->getExprLoc(), E, - S.PDiag(DiagID) - << E->getType() << T.getUnqualifiedType() - << PrettySourceValue << PrettyTargetValue - << E->getSourceRange() << SourceRange(CContext)); - } else { - S.Diag(E->getExprLoc(), DiagID) - << E->getType() << T.getUnqualifiedType() << PrettySourceValue - << PrettyTargetValue << E->getSourceRange() << SourceRange(CContext); - } + S.Diag(FL->getExprLoc(), diag::warn_impcast_literal_float_to_integer) + << FL->getType() << T.getUnqualifiedType() << PrettySourceValue + << PrettyTargetValue << FL->getSourceRange() << SourceRange(CContext); } std::string PrettyPrintInRange(const llvm::APSInt &Value, IntRange Range) { @@ -8800,7 +7002,7 @@ std::string PrettyPrintInRange(const llvm::APSInt &Value, IntRange Range) { return ValueInRange.toString(10); } -bool IsImplicitBoolFloatConversion(Sema &S, Expr *Ex, bool ToBool) { +static bool IsImplicitBoolFloatConversion(Sema &S, Expr *Ex, bool ToBool) { if (!isa<ImplicitCastExpr>(Ex)) return false; @@ -8840,7 +7042,8 @@ void CheckImplicitArgumentConversions(Sema &S, CallExpr *TheCall, } } -void DiagnoseNullConversion(Sema &S, Expr *E, QualType T, SourceLocation CC) { +static void DiagnoseNullConversion(Sema &S, Expr *E, QualType T, + SourceLocation CC) { if (S.Diags.isIgnored(diag::warn_impcast_null_pointer_to_integer, E->getExprLoc())) return; @@ -8862,21 +7065,14 @@ void DiagnoseNullConversion(Sema &S, Expr *E, QualType T, SourceLocation CC) { SourceLocation Loc = E->getSourceRange().getBegin(); - // Venture through the macro stacks to get to the source of macro arguments. - // The new location is a better location than the complete location that was - // passed in. - while (S.SourceMgr.isMacroArgExpansion(Loc)) - Loc = S.SourceMgr.getImmediateMacroCallerLoc(Loc); - - while (S.SourceMgr.isMacroArgExpansion(CC)) - CC = S.SourceMgr.getImmediateMacroCallerLoc(CC); - // __null is usually wrapped in a macro. Go up a macro if that is the case. - if (NullKind == Expr::NPCK_GNUNull && Loc.isMacroID()) { - StringRef MacroName = Lexer::getImmediateMacroNameForDiagnostics( - Loc, S.SourceMgr, S.getLangOpts()); - if (MacroName == "NULL") - Loc = S.SourceMgr.getImmediateExpansionRange(Loc).first; + if (NullKind == Expr::NPCK_GNUNull) { + if (Loc.isMacroID()) { + StringRef MacroName = + Lexer::getImmediateMacroName(Loc, S.SourceMgr, S.getLangOpts()); + if (MacroName == "NULL") + Loc = S.SourceMgr.getImmediateExpansionRange(Loc).first; + } } // Only warn if the null and context location are in the same macro expansion. @@ -8889,15 +7085,17 @@ void DiagnoseNullConversion(Sema &S, Expr *E, QualType T, SourceLocation CC) { S.getFixItZeroLiteralForType(T, Loc)); } -void checkObjCArrayLiteral(Sema &S, QualType TargetType, - ObjCArrayLiteral *ArrayLiteral); -void checkObjCDictionaryLiteral(Sema &S, QualType TargetType, - ObjCDictionaryLiteral *DictionaryLiteral); +static void checkObjCArrayLiteral(Sema &S, QualType TargetType, + ObjCArrayLiteral *ArrayLiteral); +static void checkObjCDictionaryLiteral(Sema &S, QualType TargetType, + ObjCDictionaryLiteral *DictionaryLiteral); /// Check a single element within a collection literal against the /// target element type. -void checkObjCCollectionLiteralElement(Sema &S, QualType TargetElementType, - Expr *Element, unsigned ElementKind) { +static void checkObjCCollectionLiteralElement(Sema &S, + QualType TargetElementType, + Expr *Element, + unsigned ElementKind) { // Skip a bitcast to 'id' or qualified 'id'. if (auto ICE = dyn_cast<ImplicitCastExpr>(Element)) { if (ICE->getCastKind() == CK_BitCast && @@ -8926,8 +7124,8 @@ void checkObjCCollectionLiteralElement(Sema &S, QualType TargetElementType, /// Check an Objective-C array literal being converted to the given /// target type. -void checkObjCArrayLiteral(Sema &S, QualType TargetType, - ObjCArrayLiteral *ArrayLiteral) { +static void checkObjCArrayLiteral(Sema &S, QualType TargetType, + ObjCArrayLiteral *ArrayLiteral) { if (!S.NSArrayDecl) return; @@ -8954,8 +7152,9 @@ void checkObjCArrayLiteral(Sema &S, QualType TargetType, /// Check an Objective-C dictionary literal being converted to the given /// target type. -void checkObjCDictionaryLiteral(Sema &S, QualType TargetType, - ObjCDictionaryLiteral *DictionaryLiteral) { +static void checkObjCDictionaryLiteral( + Sema &S, QualType TargetType, + ObjCDictionaryLiteral *DictionaryLiteral) { if (!S.NSDictionaryDecl) return; @@ -8981,32 +7180,6 @@ void checkObjCDictionaryLiteral(Sema &S, QualType TargetType, } } -// Helper function to filter out cases for constant width constant conversion. -// Don't warn on char array initialization or for non-decimal values. -bool isSameWidthConstantConversion(Sema &S, Expr *E, QualType T, - SourceLocation CC) { - // If initializing from a constant, and the constant starts with '0', - // then it is a binary, octal, or hexadecimal. Allow these constants - // to fill all the bits, even if there is a sign change. - if (auto *IntLit = dyn_cast<IntegerLiteral>(E->IgnoreParenImpCasts())) { - const char FirstLiteralCharacter = - S.getSourceManager().getCharacterData(IntLit->getLocStart())[0]; - if (FirstLiteralCharacter == '0') - return false; - } - - // If the CC location points to a '{', and the type is char, then assume - // assume it is an array initialization. - if (CC.isValid() && T->isCharType()) { - const char FirstContextCharacter = - S.getSourceManager().getCharacterData(CC)[0]; - if (FirstContextCharacter == '{') - return false; - } - - return true; -} - void CheckImplicitConversion(Sema &S, Expr *E, QualType T, SourceLocation CC, bool *ICContext = nullptr) { if (E->isTypeDependent() || E->isValueDependent()) return; @@ -9111,6 +7284,7 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, return; DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_float_precision); + } // ... or possibly if we're increasing rank, too else if (TargetBT->getKind() > SourceBT->getKind()) { @@ -9122,12 +7296,22 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, return; } - // If the target is integral, always warn. + // If the target is integral, always warn. if (TargetBT && TargetBT->isInteger()) { if (S.SourceMgr.isInSystemMacro(CC)) return; - - DiagnoseFloatingImpCast(S, E, T, CC); + + Expr *InnerE = E->IgnoreParenImpCasts(); + // We also want to warn on, e.g., "int i = -1.234" + if (UnaryOperator *UOp = dyn_cast<UnaryOperator>(InnerE)) + if (UOp->getOpcode() == UO_Minus || UOp->getOpcode() == UO_Plus) + InnerE = UOp->getSubExpr()->IgnoreParenImpCasts(); + + if (FloatingLiteral *FL = dyn_cast<FloatingLiteral>(InnerE)) { + DiagnoseFloatingLiteralImpCast(S, FL, T, CC); + } else { + DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_float_integer); + } } // Detect the case where a call result is converted from floating-point to @@ -9159,8 +7343,6 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, DiagnoseNullConversion(S, E, T, CC); - S.DiscardMisalignedMemberAddress(Target, E); - if (!Source->isIntegerType() || !Target->isIntegerType()) return; @@ -9176,7 +7358,7 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, // If the source is a constant, use a default-on diagnostic. // TODO: this should happen for bitfield stores, too. llvm::APSInt Value(32); - if (E->EvaluateAsInt(Value, S.Context, Expr::SE_AllowSideEffects)) { + if (E->isIntegerConstantExpr(Value, S.Context)) { if (S.SourceMgr.isInSystemMacro(CC)) return; @@ -9201,34 +7383,10 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_integer_precision); } - if (TargetRange.Width == SourceRange.Width && !TargetRange.NonNegative && - SourceRange.NonNegative && Source->isSignedIntegerType()) { - // Warn when doing a signed to signed conversion, warn if the positive - // source value is exactly the width of the target type, which will - // cause a negative value to be stored. - - llvm::APSInt Value; - if (E->EvaluateAsInt(Value, S.Context, Expr::SE_AllowSideEffects) && - !S.SourceMgr.isInSystemMacro(CC)) { - if (isSameWidthConstantConversion(S, E, T, CC)) { - std::string PrettySourceValue = Value.toString(10); - std::string PrettyTargetValue = PrettyPrintInRange(Value, TargetRange); - - S.DiagRuntimeBehavior( - E->getExprLoc(), E, - S.PDiag(diag::warn_impcast_integer_precision_constant) - << PrettySourceValue << PrettyTargetValue << E->getType() << T - << E->getSourceRange() << clang::SourceRange(CC)); - return; - } - } - - // Fall through for non-constants to give a sign conversion warning. - } - if ((TargetRange.NonNegative && !SourceRange.NonNegative) || (!TargetRange.NonNegative && SourceRange.NonNegative && SourceRange.Width == TargetRange.Width)) { + if (S.SourceMgr.isInSystemMacro(CC)) return; @@ -9271,6 +7429,8 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, return DiagnoseImpCast(S, E, SourceType, T, CC, diag::warn_impcast_different_enum_types); } + + return; } void CheckConditionalOperator(Sema &S, ConditionalOperator *E, @@ -9286,6 +7446,7 @@ void CheckConditionalOperand(Sema &S, Expr *E, QualType T, AnalyzeImplicitConversions(S, E, CC); if (E->getType() != T) return CheckImplicitConversion(S, E, T, CC, &ICContext); + return; } void CheckConditionalOperator(Sema &S, ConditionalOperator *E, @@ -9318,7 +7479,7 @@ void CheckConditionalOperator(Sema &S, ConditionalOperator *E, /// CheckBoolLikeConversion - Check conversion of given expression to boolean. /// Input argument E is a logical expression. -void CheckBoolLikeConversion(Sema &S, Expr *E, SourceLocation CC) { +static void CheckBoolLikeConversion(Sema &S, Expr *E, SourceLocation CC) { if (S.getLangOpts().Bool) return; CheckImplicitConversion(S, E->IgnoreParenImpCasts(), S.Context.BoolTy, CC); @@ -9422,25 +7583,10 @@ void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC) { } // end anonymous namespace -/// Diagnose integer type and any valid implicit convertion to it. -static bool checkOpenCLEnqueueIntType(Sema &S, Expr *E, const QualType &IntT) { - // Taking into account implicit conversions, - // allow any integer. - if (!E->getType()->isIntegerType()) { - S.Diag(E->getLocStart(), - diag::err_opencl_enqueue_kernel_invalid_local_size_type); - return true; - } - // Potentially emit standard warnings for implicit conversions if enabled - // using -Wconversion. - CheckImplicitConversion(S, E, IntT, E->getLocStart()); - return false; -} - // Helper function for Sema::DiagnoseAlwaysNonNullPointer. // Returns true when emitting a warning about taking the address of a reference. static bool CheckForReference(Sema &SemaRef, const Expr *E, - const PartialDiagnostic &PD) { + PartialDiagnostic PD) { E = E->IgnoreParenImpCasts(); const FunctionDecl *FD = nullptr; @@ -9535,8 +7681,7 @@ void Sema::DiagnoseAlwaysNonNullPointer(Expr *E, } } - auto ComplainAboutNonnullParamOrCall = [&](const Attr *NonnullAttr) { - bool IsParam = isa<NonNullAttr>(NonnullAttr); + auto ComplainAboutNonnullParamOrCall = [&](bool IsParam) { std::string Str; llvm::raw_string_ostream S(Str); E->printPretty(S, nullptr, getPrintingPolicy()); @@ -9544,14 +7689,13 @@ void Sema::DiagnoseAlwaysNonNullPointer(Expr *E, : diag::warn_cast_nonnull_to_bool; Diag(E->getExprLoc(), DiagID) << IsParam << S.str() << E->getSourceRange() << Range << IsEqual; - Diag(NonnullAttr->getLocation(), diag::note_declared_nonnull) << IsParam; }; // If we have a CallExpr that is tagged with returns_nonnull, we can complain. if (auto *Call = dyn_cast<CallExpr>(E->IgnoreParenImpCasts())) { if (auto *Callee = Call->getDirectCallee()) { - if (const Attr *A = Callee->getAttr<ReturnsNonNullAttr>()) { - ComplainAboutNonnullParamOrCall(A); + if (Callee->hasAttr<ReturnsNonNullAttr>()) { + ComplainAboutNonnullParamOrCall(false); return; } } @@ -9573,25 +7717,25 @@ void Sema::DiagnoseAlwaysNonNullPointer(Expr *E, if (const auto* PV = dyn_cast<ParmVarDecl>(D)) { if (getCurFunction() && !getCurFunction()->ModifiedNonNullParams.count(PV)) { - if (const Attr *A = PV->getAttr<NonNullAttr>()) { - ComplainAboutNonnullParamOrCall(A); + if (PV->hasAttr<NonNullAttr>()) { + ComplainAboutNonnullParamOrCall(true); return; } if (const auto *FD = dyn_cast<FunctionDecl>(PV->getDeclContext())) { - auto ParamIter = llvm::find(FD->parameters(), PV); + auto ParamIter = std::find(FD->param_begin(), FD->param_end(), PV); assert(ParamIter != FD->param_end()); unsigned ParamNo = std::distance(FD->param_begin(), ParamIter); for (const auto *NonNull : FD->specific_attrs<NonNullAttr>()) { if (!NonNull->args_size()) { - ComplainAboutNonnullParamOrCall(NonNull); + ComplainAboutNonnullParamOrCall(true); return; } for (unsigned ArgNo : NonNull->args()) { if (ArgNo == ParamNo) { - ComplainAboutNonnullParamOrCall(NonNull); + ComplainAboutNonnullParamOrCall(true); return; } } @@ -9673,6 +7817,7 @@ void Sema::DiagnoseAlwaysNonNullPointer(Expr *E, << FixItHint::CreateInsertion(getLocForEndOfToken(E->getLocEnd()), "()"); } + /// Diagnoses "dangerous" implicit conversions within the given /// expression (which is a full expression). Implements -Wconversion /// and -Wsign-compare. @@ -9707,20 +7852,12 @@ void Sema::CheckBoolLikeConversion(Expr *E, SourceLocation CC) { /// Diagnose when expression is an integer constant expression and its evaluation /// results in integer overflow void Sema::CheckForIntOverflow (Expr *E) { - // Use a work list to deal with nested struct initializers. - SmallVector<Expr *, 2> Exprs(1, E); - - do { - Expr *E = Exprs.pop_back_val(); - - if (isa<BinaryOperator>(E->IgnoreParenCasts())) { - E->IgnoreParenCasts()->EvaluateForOverflow(Context); - continue; - } - - if (auto InitList = dyn_cast<InitListExpr>(E)) - Exprs.append(InitList->inits().begin(), InitList->inits().end()); - } while (!Exprs.empty()); + if (isa<BinaryOperator>(E->IgnoreParenCasts())) + E->IgnoreParenCasts()->EvaluateForOverflow(Context); + else if (auto InitList = dyn_cast<InitListExpr>(E)) + for (Expr *E : InitList->inits()) + if (isa<BinaryOperator>(E->IgnoreParenCasts())) + E->IgnoreParenCasts()->EvaluateForOverflow(Context); } namespace { @@ -9738,7 +7875,7 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> { struct Value { explicit Value(unsigned Parent) : Parent(Parent), Merged(false) {} unsigned Parent : 31; - unsigned Merged : 1; + bool Merged : 1; }; SmallVector<Value, 8> Values; @@ -9850,11 +7987,12 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> { Self.ModAsSideEffect = &ModAsSideEffect; } ~SequencedSubexpression() { - for (auto &M : llvm::reverse(ModAsSideEffect)) { - UsageInfo &U = Self.UsageMap[M.first]; + for (auto MI = ModAsSideEffect.rbegin(), ME = ModAsSideEffect.rend(); + MI != ME; ++MI) { + UsageInfo &U = Self.UsageMap[MI->first]; auto &SideEffectUsage = U.Uses[UK_ModAsSideEffect]; - Self.addUsage(U, M.first, SideEffectUsage.Use, UK_ModAsValue); - SideEffectUsage = M.second; + Self.addUsage(U, MI->first, SideEffectUsage.Use, UK_ModAsValue); + SideEffectUsage = MI->second; } Self.ModAsSideEffect = OldModAsSideEffect; } @@ -10057,7 +8195,6 @@ public: notePostMod(O, BO, SemaRef.getLangOpts().CPlusPlus ? UK_ModAsValue : UK_ModAsSideEffect); } - void VisitCompoundAssignOperator(CompoundAssignOperator *CAO) { VisitBinAssign(CAO); } @@ -10207,7 +8344,7 @@ public: Tree.merge(Elts[I]); } }; -} // end anonymous namespace +} void Sema::CheckUnsequencedOperations(Expr *E) { SmallVector<Expr *, 8> WorkList; @@ -10221,11 +8358,9 @@ void Sema::CheckUnsequencedOperations(Expr *E) { void Sema::CheckCompletedExpr(Expr *E, SourceLocation CheckLoc, bool IsConstexpr) { CheckImplicitConversions(E, CheckLoc); - if (!E->isInstantiationDependent()) - CheckUnsequencedOperations(E); + CheckUnsequencedOperations(E); if (!IsConstexpr && !E->isValueDependent()) CheckForIntOverflow(E); - DiagnoseMisalignedMembers(); } void Sema::CheckBitFieldInitialization(SourceLocation InitLoc, @@ -10268,10 +8403,13 @@ static void diagnoseArrayStarInParamType(Sema &S, QualType PType, /// takes care of any checks that cannot be performed on the /// declaration itself, e.g., that the types of each of the function /// parameters are complete. -bool Sema::CheckParmsForFunctionDef(ArrayRef<ParmVarDecl *> Parameters, +bool Sema::CheckParmsForFunctionDef(ParmVarDecl *const *P, + ParmVarDecl *const *PEnd, bool CheckParameterNames) { bool HasInvalidParm = false; - for (ParmVarDecl *Param : Parameters) { + for (; P != PEnd; ++P) { + ParmVarDecl *Param = *P; + // C99 6.7.5.3p4: the parameters in a parameter type list in a // function declarator that is part of a function definition of // that function shall not have incomplete type. @@ -10336,19 +8474,6 @@ bool Sema::CheckParmsForFunctionDef(ArrayRef<ParmVarDecl *> Parameters, return HasInvalidParm; } -/// A helper function to get the alignment of a Decl referred to by DeclRefExpr -/// or MemberExpr. -static CharUnits getDeclAlign(Expr *E, CharUnits TypeAlign, - ASTContext &Context) { - if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) - return Context.getDeclAlign(DRE->getDecl()); - - if (const auto *ME = dyn_cast<MemberExpr>(E)) - return Context.getDeclAlign(ME->getMemberDecl()); - - return TypeAlign; -} - /// CheckCastAlign - Implements -Wcast-align, which warns when a /// pointer cast increases the alignment requirements. void Sema::CheckCastAlign(Expr *Op, QualType T, SourceRange TRange) { @@ -10383,15 +8508,6 @@ void Sema::CheckCastAlign(Expr *Op, QualType T, SourceRange TRange) { if (SrcPointee->isIncompleteType()) return; CharUnits SrcAlign = Context.getTypeAlignInChars(SrcPointee); - - if (auto *CE = dyn_cast<CastExpr>(Op)) { - if (CE->getCastKind() == CK_ArrayToPointerDecay) - SrcAlign = getDeclAlign(CE->getSubExpr(), SrcAlign, Context); - } else if (auto *UO = dyn_cast<UnaryOperator>(Op)) { - if (UO->getOpcode() == UO_AddrOf) - SrcAlign = getDeclAlign(UO->getSubExpr(), SrcAlign, Context); - } - if (SrcAlign >= DestAlign) return; Diag(TRange.getBegin(), diag::warn_cast_align) @@ -10401,12 +8517,21 @@ void Sema::CheckCastAlign(Expr *Op, QualType T, SourceRange TRange) { << TRange << Op->getSourceRange(); } +static const Type* getElementType(const Expr *BaseExpr) { + const Type* EltType = BaseExpr->getType().getTypePtr(); + if (EltType->isAnyPointerType()) + return EltType->getPointeeType().getTypePtr(); + else if (EltType->isArrayType()) + return EltType->getBaseElementTypeUnsafe(); + return EltType; +} + /// \brief Check whether this array fits the idiom of a size-one tail padded /// array member of a struct. /// /// We avoid emitting out-of-bounds access warnings for such arrays as they are /// commonly used to emulate flexible arrays in C89 code. -static bool IsTailPaddedMemberArray(Sema &S, const llvm::APInt &Size, +static bool IsTailPaddedMemberArray(Sema &S, llvm::APInt Size, const NamedDecl *ND) { if (Size != 1 || !ND) return false; @@ -10455,8 +8580,7 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr, if (IndexExpr->isValueDependent()) return; - const Type *EffectiveType = - BaseExpr->getType()->getPointeeOrArrayElementType(); + const Type *EffectiveType = getElementType(BaseExpr); BaseExpr = BaseExpr->IgnoreParenCasts(); const ConstantArrayType *ArrayTy = Context.getAsConstantArrayType(BaseExpr->getType()); @@ -10480,7 +8604,7 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr, if (!size.isStrictlyPositive()) return; - const Type *BaseType = BaseExpr->getType()->getPointeeOrArrayElementType(); + const Type* BaseType = getElementType(BaseExpr); if (BaseType != EffectiveType) { // Make sure we're comparing apples to apples when comparing index to size uint64_t ptrarith_typesize = Context.getTypeSize(EffectiveType); @@ -10630,7 +8754,7 @@ namespace { Range = e->getSourceRange(); } }; -} // end anonymous namespace +} /// Consider whether capturing the given variable can possibly lead to /// a retain cycle. @@ -10776,7 +8900,7 @@ namespace { } } }; -} // end anonymous namespace +} /// Check whether the given argument is a block which captures a /// variable. @@ -11012,6 +9136,7 @@ void Sema::CheckObjCCircularContainer(ObjCMessageExpr *Message) { } } } + } /// Check a message send to see if it's likely to cause a retain cycle. @@ -11215,7 +9340,7 @@ bool ShouldDiagnoseEmptyStmtBody(const SourceManager &SourceMgr, return true; } -} // end anonymous namespace +} // Unnamed namespace void Sema::DiagnoseEmptyStmtBody(SourceLocation StmtLoc, const Stmt *Body, @@ -11311,6 +9436,7 @@ void Sema::DiagnoseEmptyLoopBody(const Stmt *S, /// DiagnoseSelfMove - Emits a warning if a value is moved to itself. void Sema::DiagnoseSelfMove(const Expr *LHSExpr, const Expr *RHSExpr, SourceLocation OpLoc) { + if (Diags.isIgnored(diag::warn_sizeof_pointer_expr_memaccess, OpLoc)) return; @@ -11549,7 +9675,7 @@ bool isLayoutCompatible(ASTContext &C, QualType T1, QualType T2) { return false; } -} // end anonymous namespace +} //===--- CHECK: pointer_with_type_tag attribute: datatypes should match ----// @@ -11680,7 +9806,7 @@ bool GetMatchingCType( TypeInfo = I->second; return true; } -} // end anonymous namespace +} // unnamed namespace void Sema::RegisterTypeTagForDatatype(const IdentifierInfo *ArgumentKind, uint64_t MagicValue, QualType Type, @@ -11713,7 +9839,7 @@ bool IsSameCharType(QualType T1, QualType T2) { (T1Kind == BuiltinType::Char_U && T2Kind == BuiltinType::UChar) || (T1Kind == BuiltinType::Char_S && T2Kind == BuiltinType::SChar); } -} // end anonymous namespace +} // unnamed namespace void Sema::CheckArgumentWithTypeTag(const ArgumentWithTypeTagAttr *Attr, const Expr * const *ExprArgs) { @@ -11793,151 +9919,3 @@ void Sema::CheckArgumentWithTypeTag(const ArgumentWithTypeTagAttr *Attr, << ArgumentExpr->getSourceRange() << TypeTagExpr->getSourceRange(); } - -void Sema::AddPotentialMisalignedMembers(Expr *E, RecordDecl *RD, ValueDecl *MD, - CharUnits Alignment) { - MisalignedMembers.emplace_back(E, RD, MD, Alignment); -} - -void Sema::DiagnoseMisalignedMembers() { - for (MisalignedMember &m : MisalignedMembers) { - const NamedDecl *ND = m.RD; - if (ND->getName().empty()) { - if (const TypedefNameDecl *TD = m.RD->getTypedefNameForAnonDecl()) - ND = TD; - } - Diag(m.E->getLocStart(), diag::warn_taking_address_of_packed_member) - << m.MD << ND << m.E->getSourceRange(); - } - MisalignedMembers.clear(); -} - -void Sema::DiscardMisalignedMemberAddress(const Type *T, Expr *E) { - E = E->IgnoreParens(); - if (!T->isPointerType() && !T->isIntegerType()) - return; - if (isa<UnaryOperator>(E) && - cast<UnaryOperator>(E)->getOpcode() == UO_AddrOf) { - auto *Op = cast<UnaryOperator>(E)->getSubExpr()->IgnoreParens(); - if (isa<MemberExpr>(Op)) { - auto MA = std::find(MisalignedMembers.begin(), MisalignedMembers.end(), - MisalignedMember(Op)); - if (MA != MisalignedMembers.end() && - (T->isIntegerType() || - (T->isPointerType() && - Context.getTypeAlignInChars(T->getPointeeType()) <= MA->Alignment))) - MisalignedMembers.erase(MA); - } - } -} - -void Sema::RefersToMemberWithReducedAlignment( - Expr *E, - llvm::function_ref<void(Expr *, RecordDecl *, FieldDecl *, CharUnits)> - Action) { - const auto *ME = dyn_cast<MemberExpr>(E); - if (!ME) - return; - - // For a chain of MemberExpr like "a.b.c.d" this list - // will keep FieldDecl's like [d, c, b]. - SmallVector<FieldDecl *, 4> ReverseMemberChain; - const MemberExpr *TopME = nullptr; - bool AnyIsPacked = false; - do { - QualType BaseType = ME->getBase()->getType(); - if (ME->isArrow()) - BaseType = BaseType->getPointeeType(); - RecordDecl *RD = BaseType->getAs<RecordType>()->getDecl(); - - ValueDecl *MD = ME->getMemberDecl(); - auto *FD = dyn_cast<FieldDecl>(MD); - // We do not care about non-data members. - if (!FD || FD->isInvalidDecl()) - return; - - AnyIsPacked = - AnyIsPacked || (RD->hasAttr<PackedAttr>() || MD->hasAttr<PackedAttr>()); - ReverseMemberChain.push_back(FD); - - TopME = ME; - ME = dyn_cast<MemberExpr>(ME->getBase()->IgnoreParens()); - } while (ME); - assert(TopME && "We did not compute a topmost MemberExpr!"); - - // Not the scope of this diagnostic. - if (!AnyIsPacked) - return; - - const Expr *TopBase = TopME->getBase()->IgnoreParenImpCasts(); - const auto *DRE = dyn_cast<DeclRefExpr>(TopBase); - // TODO: The innermost base of the member expression may be too complicated. - // For now, just disregard these cases. This is left for future - // improvement. - if (!DRE && !isa<CXXThisExpr>(TopBase)) - return; - - // Alignment expected by the whole expression. - CharUnits ExpectedAlignment = Context.getTypeAlignInChars(E->getType()); - - // No need to do anything else with this case. - if (ExpectedAlignment.isOne()) - return; - - // Synthesize offset of the whole access. - CharUnits Offset; - for (auto I = ReverseMemberChain.rbegin(); I != ReverseMemberChain.rend(); - I++) { - Offset += Context.toCharUnitsFromBits(Context.getFieldOffset(*I)); - } - - // Compute the CompleteObjectAlignment as the alignment of the whole chain. - CharUnits CompleteObjectAlignment = Context.getTypeAlignInChars( - ReverseMemberChain.back()->getParent()->getTypeForDecl()); - - // The base expression of the innermost MemberExpr may give - // stronger guarantees than the class containing the member. - if (DRE && !TopME->isArrow()) { - const ValueDecl *VD = DRE->getDecl(); - if (!VD->getType()->isReferenceType()) - CompleteObjectAlignment = - std::max(CompleteObjectAlignment, Context.getDeclAlign(VD)); - } - - // Check if the synthesized offset fulfills the alignment. - if (Offset % ExpectedAlignment != 0 || - // It may fulfill the offset it but the effective alignment may still be - // lower than the expected expression alignment. - CompleteObjectAlignment < ExpectedAlignment) { - // If this happens, we want to determine a sensible culprit of this. - // Intuitively, watching the chain of member expressions from right to - // left, we start with the required alignment (as required by the field - // type) but some packed attribute in that chain has reduced the alignment. - // It may happen that another packed structure increases it again. But if - // we are here such increase has not been enough. So pointing the first - // FieldDecl that either is packed or else its RecordDecl is, - // seems reasonable. - FieldDecl *FD = nullptr; - CharUnits Alignment; - for (FieldDecl *FDI : ReverseMemberChain) { - if (FDI->hasAttr<PackedAttr>() || - FDI->getParent()->hasAttr<PackedAttr>()) { - FD = FDI; - Alignment = std::min( - Context.getTypeAlignInChars(FD->getType()), - Context.getTypeAlignInChars(FD->getParent()->getTypeForDecl())); - break; - } - } - assert(FD && "We did not find a packed FieldDecl!"); - Action(E, FD->getParent(), FD, Alignment); - } -} - -void Sema::CheckAddressOfPackedMember(Expr *rhs) { - using namespace std::placeholders; - RefersToMemberWithReducedAlignment( - rhs, std::bind(&Sema::AddPotentialMisalignedMembers, std::ref(*this), _1, - _2, _3, _4)); -} - diff --git a/gnu/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp b/gnu/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp index c6a5bc74145..f94c822b90f 100644 --- a/gnu/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp +++ b/gnu/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp @@ -11,9 +11,8 @@ // //===----------------------------------------------------------------------===// -#include "clang/AST/ASTConsumer.h" +#include "clang/Sema/SemaInternal.h" #include "clang/AST/ASTContext.h" -#include "clang/AST/ASTMutationListener.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" @@ -21,21 +20,17 @@ #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/Mangle.h" -#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/ASTMutationListener.h" #include "clang/Basic/CharInfo.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/DelayedDiagnostic.h" -#include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/Scope.h" -#include "clang/Sema/SemaInternal.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/MathExtras.h" - using namespace clang; using namespace sema; @@ -45,7 +40,7 @@ namespace AttributeLangSupport { Cpp, ObjC }; -} // end namespace AttributeLangSupport +} //===----------------------------------------------------------------------===// // Helper functions @@ -57,7 +52,6 @@ namespace AttributeLangSupport { static bool isFunctionOrMethod(const Decl *D) { return (D->getFunctionType() != nullptr) || isa<ObjCMethodDecl>(D); } - /// \brief Return true if the given decl has function type (function or /// function-typed variable) or an Objective-C method or a block. static bool isFunctionOrMethodOrBlock(const Decl *D) { @@ -247,28 +241,6 @@ static bool checkUInt32Argument(Sema &S, const AttributeList &Attr, return true; } -/// \brief Wrapper around checkUInt32Argument, with an extra check to be sure -/// that the result will fit into a regular (signed) int. All args have the same -/// purpose as they do in checkUInt32Argument. -static bool checkPositiveIntArgument(Sema &S, const AttributeList &Attr, - const Expr *Expr, int &Val, - unsigned Idx = UINT_MAX) { - uint32_t UVal; - if (!checkUInt32Argument(S, Attr, Expr, UVal, Idx)) - return false; - - if (UVal > (uint32_t)std::numeric_limits<int>::max()) { - llvm::APSInt I(32); // for toString - I = UVal; - S.Diag(Expr->getExprLoc(), diag::err_ice_too_large) - << I.toString(10, false) << 32 << /* Unsigned */ 0; - return false; - } - - Val = UVal; - return true; -} - /// \brief Diagnose mutually exclusive attributes when present on a given /// declaration. Returns true if diagnosed. template <typename AttrTy> @@ -753,69 +725,6 @@ static void handleAssertExclusiveLockAttr(Sema &S, Decl *D, Attr.getAttributeSpellingListIndex())); } -/// \brief Checks to be sure that the given parameter number is inbounds, and is -/// an some integral type. Will emit appropriate diagnostics if this returns -/// false. -/// -/// FuncParamNo is expected to be from the user, so is base-1. AttrArgNo is used -/// to actually retrieve the argument, so it's base-0. -static bool checkParamIsIntegerType(Sema &S, const FunctionDecl *FD, - const AttributeList &Attr, - unsigned FuncParamNo, unsigned AttrArgNo) { - assert(Attr.isArgExpr(AttrArgNo) && "Expected expression argument"); - uint64_t Idx; - if (!checkFunctionOrMethodParameterIndex(S, FD, Attr, FuncParamNo, - Attr.getArgAsExpr(AttrArgNo), Idx)) - return false; - - const ParmVarDecl *Param = FD->getParamDecl(Idx); - if (!Param->getType()->isIntegerType() && !Param->getType()->isCharType()) { - SourceLocation SrcLoc = Attr.getArgAsExpr(AttrArgNo)->getLocStart(); - S.Diag(SrcLoc, diag::err_attribute_integers_only) - << Attr.getName() << Param->getSourceRange(); - return false; - } - return true; -} - -static void handleAllocSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) { - if (!checkAttributeAtLeastNumArgs(S, Attr, 1) || - !checkAttributeAtMostNumArgs(S, Attr, 2)) - return; - - const auto *FD = cast<FunctionDecl>(D); - if (!FD->getReturnType()->isPointerType()) { - S.Diag(Attr.getLoc(), diag::warn_attribute_return_pointers_only) - << Attr.getName(); - return; - } - - const Expr *SizeExpr = Attr.getArgAsExpr(0); - int SizeArgNo; - // Paramater indices are 1-indexed, hence Index=1 - if (!checkPositiveIntArgument(S, Attr, SizeExpr, SizeArgNo, /*Index=*/1)) - return; - - if (!checkParamIsIntegerType(S, FD, Attr, SizeArgNo, /*AttrArgNo=*/0)) - return; - - // Args are 1-indexed, so 0 implies that the arg was not present - int NumberArgNo = 0; - if (Attr.getNumArgs() == 2) { - const Expr *NumberExpr = Attr.getArgAsExpr(1); - // Paramater indices are 1-based, hence Index=2 - if (!checkPositiveIntArgument(S, Attr, NumberExpr, NumberArgNo, - /*Index=*/2)) - return; - - if (!checkParamIsIntegerType(S, FD, Attr, NumberArgNo, /*AttrArgNo=*/1)) - return; - } - - D->addAttr(::new (S.Context) AllocSizeAttr( - Attr.getRange(), S.Context, SizeArgNo, NumberArgNo, - Attr.getAttributeSpellingListIndex())); -} static bool checkTryLockFunAttrCommon(Sema &S, Decl *D, const AttributeList &Attr, @@ -891,117 +800,32 @@ static void handleLocksExcludedAttr(Sema &S, Decl *D, Attr.getAttributeSpellingListIndex())); } -static bool checkFunctionConditionAttr(Sema &S, Decl *D, - const AttributeList &Attr, - Expr *&Cond, StringRef &Msg) { - Cond = Attr.getArgAsExpr(0); +static void handleEnableIfAttr(Sema &S, Decl *D, const AttributeList &Attr) { + Expr *Cond = Attr.getArgAsExpr(0); if (!Cond->isTypeDependent()) { ExprResult Converted = S.PerformContextuallyConvertToBool(Cond); if (Converted.isInvalid()) - return false; + return; Cond = Converted.get(); } + StringRef Msg; if (!S.checkStringLiteralArgumentAttr(Attr, 1, Msg)) - return false; - - if (Msg.empty()) - Msg = "<no message provided>"; + return; SmallVector<PartialDiagnosticAt, 8> Diags; if (!Cond->isValueDependent() && !Expr::isPotentialConstantExprUnevaluated(Cond, cast<FunctionDecl>(D), Diags)) { - S.Diag(Attr.getLoc(), diag::err_attr_cond_never_constant_expr) - << Attr.getName(); - for (const PartialDiagnosticAt &PDiag : Diags) - S.Diag(PDiag.first, PDiag.second); - return false; - } - return true; -} - -static void handleEnableIfAttr(Sema &S, Decl *D, const AttributeList &Attr) { - S.Diag(Attr.getLoc(), diag::ext_clang_enable_if); - - Expr *Cond; - StringRef Msg; - if (checkFunctionConditionAttr(S, D, Attr, Cond, Msg)) - D->addAttr(::new (S.Context) - EnableIfAttr(Attr.getRange(), S.Context, Cond, Msg, - Attr.getAttributeSpellingListIndex())); -} - -namespace { -/// Determines if a given Expr references any of the given function's -/// ParmVarDecls, or the function's implicit `this` parameter (if applicable). -class ArgumentDependenceChecker - : public RecursiveASTVisitor<ArgumentDependenceChecker> { -#ifndef NDEBUG - const CXXRecordDecl *ClassType; -#endif - llvm::SmallPtrSet<const ParmVarDecl *, 16> Parms; - bool Result; - -public: - ArgumentDependenceChecker(const FunctionDecl *FD) { -#ifndef NDEBUG - if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) - ClassType = MD->getParent(); - else - ClassType = nullptr; -#endif - Parms.insert(FD->param_begin(), FD->param_end()); - } - - bool referencesArgs(Expr *E) { - Result = false; - TraverseStmt(E); - return Result; - } - - bool VisitCXXThisExpr(CXXThisExpr *E) { - assert(E->getType()->getPointeeCXXRecordDecl() == ClassType && - "`this` doesn't refer to the enclosing class?"); - Result = true; - return false; - } - - bool VisitDeclRefExpr(DeclRefExpr *DRE) { - if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) - if (Parms.count(PVD)) { - Result = true; - return false; - } - return true; - } -}; -} - -static void handleDiagnoseIfAttr(Sema &S, Decl *D, const AttributeList &Attr) { - S.Diag(Attr.getLoc(), diag::ext_clang_diagnose_if); - - Expr *Cond; - StringRef Msg; - if (!checkFunctionConditionAttr(S, D, Attr, Cond, Msg)) - return; - - StringRef DiagTypeStr; - if (!S.checkStringLiteralArgumentAttr(Attr, 2, DiagTypeStr)) - return; - - DiagnoseIfAttr::DiagnosticType DiagType; - if (!DiagnoseIfAttr::ConvertStrToDiagnosticType(DiagTypeStr, DiagType)) { - S.Diag(Attr.getArgAsExpr(2)->getLocStart(), - diag::err_diagnose_if_invalid_diagnostic_type); + S.Diag(Attr.getLoc(), diag::err_enable_if_never_constant_expr); + for (int I = 0, N = Diags.size(); I != N; ++I) + S.Diag(Diags[I].first, Diags[I].second); return; } - auto *FD = cast<FunctionDecl>(D); - bool ArgDependent = ArgumentDependenceChecker(FD).referencesArgs(Cond); - D->addAttr(::new (S.Context) DiagnoseIfAttr( - Attr.getRange(), S.Context, Cond, Msg, DiagType, ArgDependent, FD, - Attr.getAttributeSpellingListIndex())); + D->addAttr(::new (S.Context) + EnableIfAttr(Attr.getRange(), S.Context, Cond, Msg, + Attr.getAttributeSpellingListIndex())); } static void handlePassObjectSizeAttr(Sema &S, Decl *D, @@ -1063,6 +887,7 @@ static void handleConsumableAttr(Sema &S, Decl *D, const AttributeList &Attr) { Attr.getAttributeSpellingListIndex())); } + static bool checkForConsumableClass(Sema &S, const CXXMethodDecl *MD, const AttributeList &Attr) { ASTContext &CurrContext = S.getASTContext(); @@ -1080,6 +905,7 @@ static bool checkForConsumableClass(Sema &S, const CXXMethodDecl *MD, return true; } + static void handleCallableWhenAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (!checkAttributeAtLeastNumArgs(S, Attr, 1)) @@ -1118,6 +944,7 @@ static void handleCallableWhenAttr(Sema &S, Decl *D, States.size(), Attr.getAttributeSpellingListIndex())); } + static void handleParamTypestateAttr(Sema &S, Decl *D, const AttributeList &Attr) { ParamTypestateAttr::ConsumedState ParamState; @@ -1155,6 +982,7 @@ static void handleParamTypestateAttr(Sema &S, Decl *D, Attr.getAttributeSpellingListIndex())); } + static void handleReturnTypestateAttr(Sema &S, Decl *D, const AttributeList &Attr) { ReturnTypestateAttr::ConsumedState ReturnState; @@ -1203,6 +1031,7 @@ static void handleReturnTypestateAttr(Sema &S, Decl *D, Attr.getAttributeSpellingListIndex())); } + static void handleSetTypestateAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), Attr)) return; @@ -1719,28 +1548,6 @@ static void handleWeakRefAttr(Sema &S, Decl *D, const AttributeList &Attr) { Attr.getAttributeSpellingListIndex())); } -static void handleIFuncAttr(Sema &S, Decl *D, const AttributeList &Attr) { - StringRef Str; - if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str)) - return; - - // Aliases should be on declarations, not definitions. - const auto *FD = cast<FunctionDecl>(D); - if (FD->isThisDeclarationADefinition()) { - S.Diag(Attr.getLoc(), diag::err_alias_is_definition) << FD << 1; - return; - } - // FIXME: it should be handled as a target specific attribute. - if (S.Context.getTargetInfo().getTriple().getObjectFormat() != - llvm::Triple::ELF) { - S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); - return; - } - - D->addAttr(::new (S.Context) IFuncAttr(Attr.getRange(), S.Context, Str, - Attr.getAttributeSpellingListIndex())); -} - static void handleAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) { StringRef Str; if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str)) @@ -1750,20 +1557,17 @@ static void handleAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) { S.Diag(Attr.getLoc(), diag::err_alias_not_supported_on_darwin); return; } - if (S.Context.getTargetInfo().getTriple().isNVPTX()) { - S.Diag(Attr.getLoc(), diag::err_alias_not_supported_on_nvptx); - } // Aliases should be on declarations, not definitions. if (const auto *FD = dyn_cast<FunctionDecl>(D)) { if (FD->isThisDeclarationADefinition()) { - S.Diag(Attr.getLoc(), diag::err_alias_is_definition) << FD << 0; + S.Diag(Attr.getLoc(), diag::err_alias_is_definition) << FD; return; } } else { const auto *VD = cast<VarDecl>(D); if (VD->isThisDeclarationADefinition() && VD->isExternallyVisible()) { - S.Diag(Attr.getLoc(), diag::err_alias_is_definition) << VD << 0; + S.Diag(Attr.getLoc(), diag::err_alias_is_definition) << VD; return; } } @@ -2000,28 +1804,6 @@ static void handleUsedAttr(Sema &S, Decl *D, const AttributeList &Attr) { Attr.getAttributeSpellingListIndex())); } -static void handleUnusedAttr(Sema &S, Decl *D, const AttributeList &Attr) { - bool IsCXX1zAttr = Attr.isCXX11Attribute() && !Attr.getScopeName(); - - if (IsCXX1zAttr && isa<VarDecl>(D)) { - // The C++1z spelling of this attribute cannot be applied to a static data - // member per [dcl.attr.unused]p2. - if (cast<VarDecl>(D)->isStaticDataMember()) { - S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << ExpectedForMaybeUnused; - return; - } - } - - // If this is spelled as the standard C++1z attribute, but not in C++1z, warn - // about using it as an extension. - if (!S.getLangOpts().CPlusPlus1z && IsCXX1zAttr) - S.Diag(Attr.getLoc(), diag::ext_cxx1z_attr) << Attr.getName(); - - D->addAttr(::new (S.Context) UnusedAttr( - Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex())); -} - static void handleConstructorAttr(Sema &S, Decl *D, const AttributeList &Attr) { uint32_t priority = ConstructorAttr::DefaultPriority; if (Attr.getNumArgs() && @@ -2128,14 +1910,11 @@ static bool versionsMatch(const VersionTuple &X, const VersionTuple &Y, AvailabilityAttr *Sema::mergeAvailabilityAttr(NamedDecl *D, SourceRange Range, IdentifierInfo *Platform, - bool Implicit, VersionTuple Introduced, VersionTuple Deprecated, VersionTuple Obsoleted, bool IsUnavailable, StringRef Message, - bool IsStrict, - StringRef Replacement, AvailabilityMergeKind AMK, unsigned AttrSpellingListIndex) { VersionTuple MergedIntroduced = Introduced; @@ -2173,14 +1952,14 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr(NamedDecl *D, SourceRange Range, // If there is an existing availability attribute for this platform that // is explicit and the new one is implicit use the explicit one and // discard the new implicit attribute. - if (!OldAA->isImplicit() && Implicit) { + if (OldAA->getRange().isValid() && Range.isInvalid()) { return nullptr; } // If there is an existing attribute for this platform that is implicit // and the new attribute is explicit then erase the old one and // continue processing the attributes. - if (!Implicit && OldAA->isImplicit()) { + if (Range.isValid() && OldAA->getRange().isInvalid()) { Attrs.erase(Attrs.begin() + i); --e; continue; @@ -2279,13 +2058,10 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr(NamedDecl *D, SourceRange Range, if (!checkAvailabilityAttr(*this, Range, Platform, MergedIntroduced, MergedDeprecated, MergedObsoleted) && !OverrideOrImpl) { - auto *Avail = ::new (Context) AvailabilityAttr(Range, Context, Platform, + return ::new (Context) AvailabilityAttr(Range, Context, Platform, Introduced, Deprecated, Obsoleted, IsUnavailable, Message, - IsStrict, Replacement, AttrSpellingListIndex); - Avail->setImplicit(Implicit); - return Avail; } return nullptr; } @@ -2312,23 +2088,16 @@ static void handleAvailabilityAttr(Sema &S, Decl *D, AvailabilityChange Deprecated = Attr.getAvailabilityDeprecated(); AvailabilityChange Obsoleted = Attr.getAvailabilityObsoleted(); bool IsUnavailable = Attr.getUnavailableLoc().isValid(); - bool IsStrict = Attr.getStrictLoc().isValid(); StringRef Str; if (const StringLiteral *SE = dyn_cast_or_null<StringLiteral>(Attr.getMessageExpr())) Str = SE->getString(); - StringRef Replacement; - if (const StringLiteral *SE = - dyn_cast_or_null<StringLiteral>(Attr.getReplacementExpr())) - Replacement = SE->getString(); AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(ND, Attr.getRange(), II, - false/*Implicit*/, Introduced.Version, Deprecated.Version, Obsoleted.Version, IsUnavailable, Str, - IsStrict, Replacement, Sema::AMK_None, Index); if (NewAttr) @@ -2367,15 +2136,12 @@ static void handleAvailabilityAttr(Sema &S, Decl *D, auto NewObsoleted = adjustWatchOSVersion(Obsoleted.Version); AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(ND, - Attr.getRange(), + SourceRange(), NewII, - true/*Implicit*/, NewIntroduced, NewDeprecated, NewObsoleted, IsUnavailable, Str, - IsStrict, - Replacement, Sema::AMK_None, Index); if (NewAttr) @@ -2392,15 +2158,12 @@ static void handleAvailabilityAttr(Sema &S, Decl *D, if (NewII) { AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(ND, - Attr.getRange(), + SourceRange(), NewII, - true/*Implicit*/, Introduced.Version, Deprecated.Version, Obsoleted.Version, IsUnavailable, Str, - IsStrict, - Replacement, Sema::AMK_None, Index); if (NewAttr) @@ -2692,12 +2455,6 @@ static void handleWarnUnusedResult(Sema &S, Decl *D, const AttributeList &Attr) return; } - // If this is spelled as the standard C++1z attribute, but not in C++1z, warn - // about using it as an extension. - if (!S.getLangOpts().CPlusPlus1z && Attr.isCXX11Attribute() && - !Attr.getScopeName()) - S.Diag(Attr.getLoc(), diag::ext_cxx1z_attr) << Attr.getName(); - D->addAttr(::new (S.Context) WarnUnusedResultAttr(Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex())); @@ -2854,6 +2611,7 @@ static void handleTargetAttr(Sema &S, Decl *D, const AttributeList &Attr) { D->addAttr(NewAttr); } + static void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &Attr) { VarDecl *VD = cast<VarDecl>(D); if (!VD->hasLocalStorage()) { @@ -2973,21 +2731,20 @@ enum FormatAttrKind { /// types. static FormatAttrKind getFormatAttrKind(StringRef Format) { return llvm::StringSwitch<FormatAttrKind>(Format) - // Check for formats that get handled specially. - .Case("NSString", NSStringFormat) - .Case("CFString", CFStringFormat) - .Case("strftime", StrftimeFormat) + // Check for formats that get handled specially. + .Case("NSString", NSStringFormat) + .Case("CFString", CFStringFormat) + .Case("strftime", StrftimeFormat) - // Otherwise, check for supported formats. - .Cases("scanf", "printf", "printf0", "strfmon", SupportedFormat) - .Cases("cmn_err", "vcmn_err", "zcmn_err", SupportedFormat) - .Case("kprintf", SupportedFormat) // OpenBSD. - .Case("freebsd_kprintf", SupportedFormat) // FreeBSD. - .Case("os_trace", SupportedFormat) - .Case("os_log", SupportedFormat) + // Otherwise, check for supported formats. + .Cases("scanf", "printf", "printf0", "strfmon", SupportedFormat) + .Cases("cmn_err", "vcmn_err", "zcmn_err", SupportedFormat) + .Case("kprintf", SupportedFormat) // OpenBSD. + .Case("freebsd_kprintf", SupportedFormat) // FreeBSD. + .Case("os_trace", SupportedFormat) - .Cases("gcc_diag", "gcc_cdiag", "gcc_cxxdiag", "gcc_tdiag", IgnoredFormat) - .Default(InvalidFormat); + .Cases("gcc_diag", "gcc_cdiag", "gcc_cxxdiag", "gcc_tdiag", IgnoredFormat) + .Default(InvalidFormat); } /// Handle __attribute__((init_priority(priority))) attributes based on @@ -3214,14 +2971,10 @@ static void handleTransparentUnionAttr(Sema &S, Decl *D, return; } - if (FirstType->isIncompleteType()) - return; uint64_t FirstSize = S.Context.getTypeSize(FirstType); uint64_t FirstAlign = S.Context.getTypeAlign(FirstType); for (; Field != FieldEnd; ++Field) { QualType FieldType = Field->getType(); - if (FieldType->isIncompleteType()) - return; // FIXME: this isn't fully correct; we also need to test whether the // members of the union would all have the same calling convention as the // first member of the union. Checking just the size and alignment isn't @@ -3316,6 +3069,7 @@ void Sema::AddAlignValueAttr(SourceRange AttrRange, Decl *D, Expr *E, // Save dependent expressions in the AST to be instantiated. D->addAttr(::new (Context) AlignValueAttr(TmpAttr)); + return; } static void handleAlignedAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -3539,8 +3293,6 @@ bool Sema::checkMSInheritanceAttrOnDefinition( /// attribute. static void parseModeAttrArg(Sema &S, StringRef Str, unsigned &DestWidth, bool &IntegerMode, bool &ComplexMode) { - IntegerMode = true; - ComplexMode = false; switch (Str.size()) { case 2: switch (Str[0]) { @@ -3576,7 +3328,7 @@ static void parseModeAttrArg(Sema &S, StringRef Str, unsigned &DestWidth, // FIXME: glibc uses 'word' to define register_t; this is narrower than a // pointer on PIC16 and other embedded platforms. if (Str == "word") - DestWidth = S.Context.getTargetInfo().getRegisterWidth(); + DestWidth = S.Context.getTargetInfo().getPointerWidth(0); else if (Str == "byte") DestWidth = S.Context.getTargetInfo().getCharWidth(); break; @@ -3607,15 +3359,9 @@ static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) { } IdentifierInfo *Name = Attr.getArgAsIdent(0)->Ident; - - S.AddModeAttr(Attr.getRange(), D, Name, Attr.getAttributeSpellingListIndex()); -} - -void Sema::AddModeAttr(SourceRange AttrRange, Decl *D, IdentifierInfo *Name, - unsigned SpellingListIndex, bool InInstantiation) { StringRef Str = Name->getName(); + normalizeName(Str); - SourceLocation AttrLoc = AttrRange.getBegin(); unsigned DestWidth = 0; bool IntegerMode = true; @@ -3631,43 +3377,25 @@ void Sema::AddModeAttr(SourceRange AttrRange, Decl *D, IdentifierInfo *Name, if (VectorStringLength && !Str.substr(1, VectorStringLength).getAsInteger(10, VectorSize) && VectorSize.isPowerOf2()) { - parseModeAttrArg(*this, Str.substr(VectorStringLength + 1), DestWidth, + parseModeAttrArg(S, Str.substr(VectorStringLength + 1), DestWidth, IntegerMode, ComplexMode); - // Avoid duplicate warning from template instantiation. - if (!InInstantiation) - Diag(AttrLoc, diag::warn_vector_mode_deprecated); + S.Diag(Attr.getLoc(), diag::warn_vector_mode_deprecated); } else { VectorSize = 0; } } if (!VectorSize) - parseModeAttrArg(*this, Str, DestWidth, IntegerMode, ComplexMode); - - // FIXME: Sync this with InitializePredefinedMacros; we need to match int8_t - // and friends, at least with glibc. - // FIXME: Make sure floating-point mappings are accurate - // FIXME: Support XF and TF types - if (!DestWidth) { - Diag(AttrLoc, diag::err_machine_mode) << 0 /*Unknown*/ << Name; - return; - } + parseModeAttrArg(S, Str, DestWidth, IntegerMode, ComplexMode); QualType OldTy; if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) OldTy = TD->getUnderlyingType(); - else if (EnumDecl *ED = dyn_cast<EnumDecl>(D)) { - // Something like 'typedef enum { X } __attribute__((mode(XX))) T;'. - // Try to get type from enum declaration, default to int. - OldTy = ED->getIntegerType(); - if (OldTy.isNull()) - OldTy = Context.IntTy; - } else - OldTy = cast<ValueDecl>(D)->getType(); - - if (OldTy->isDependentType()) { - D->addAttr(::new (Context) - ModeAttr(AttrRange, Context, Name, SpellingListIndex)); + else if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) + OldTy = VD->getType(); + else { + S.Diag(D->getLocation(), diag::err_attr_wrong_decl) + << Attr.getName() << Attr.getRange(); return; } @@ -3677,83 +3405,91 @@ void Sema::AddModeAttr(SourceRange AttrRange, Decl *D, IdentifierInfo *Name, if (const VectorType *VT = OldTy->getAs<VectorType>()) OldElemTy = VT->getElementType(); - // GCC allows 'mode' attribute on enumeration types (even incomplete), except - // for vector modes. So, 'enum X __attribute__((mode(QI)));' forms a complete - // type, 'enum { A } __attribute__((mode(V4SI)))' is rejected. - if ((isa<EnumDecl>(D) || OldElemTy->getAs<EnumType>()) && - VectorSize.getBoolValue()) { - Diag(AttrLoc, diag::err_enum_mode_vector_type) << Name << AttrRange; - return; - } - bool IntegralOrAnyEnumType = - OldElemTy->isIntegralOrEnumerationType() || OldElemTy->getAs<EnumType>(); - - if (!OldElemTy->getAs<BuiltinType>() && !OldElemTy->isComplexType() && - !IntegralOrAnyEnumType) - Diag(AttrLoc, diag::err_mode_not_primitive); + if (!OldElemTy->getAs<BuiltinType>() && !OldElemTy->isComplexType()) + S.Diag(Attr.getLoc(), diag::err_mode_not_primitive); else if (IntegerMode) { - if (!IntegralOrAnyEnumType) - Diag(AttrLoc, diag::err_mode_wrong_type); + if (!OldElemTy->isIntegralOrEnumerationType()) + S.Diag(Attr.getLoc(), diag::err_mode_wrong_type); } else if (ComplexMode) { if (!OldElemTy->isComplexType()) - Diag(AttrLoc, diag::err_mode_wrong_type); + S.Diag(Attr.getLoc(), diag::err_mode_wrong_type); } else { if (!OldElemTy->isFloatingType()) - Diag(AttrLoc, diag::err_mode_wrong_type); + S.Diag(Attr.getLoc(), diag::err_mode_wrong_type); + } + + // FIXME: Sync this with InitializePredefinedMacros; we need to match int8_t + // and friends, at least with glibc. + // FIXME: Make sure floating-point mappings are accurate + // FIXME: Support XF and TF types + if (!DestWidth) { + S.Diag(Attr.getLoc(), diag::err_machine_mode) << 0 /*Unknown*/ << Name; + return; } QualType NewElemTy; if (IntegerMode) - NewElemTy = Context.getIntTypeForBitwidth(DestWidth, - OldElemTy->isSignedIntegerType()); + NewElemTy = S.Context.getIntTypeForBitwidth( + DestWidth, OldElemTy->isSignedIntegerType()); else - NewElemTy = Context.getRealTypeForBitwidth(DestWidth); + NewElemTy = S.Context.getRealTypeForBitwidth(DestWidth); if (NewElemTy.isNull()) { - Diag(AttrLoc, diag::err_machine_mode) << 1 /*Unsupported*/ << Name; + S.Diag(Attr.getLoc(), diag::err_machine_mode) << 1 /*Unsupported*/ << Name; return; } if (ComplexMode) { - NewElemTy = Context.getComplexType(NewElemTy); + NewElemTy = S.Context.getComplexType(NewElemTy); } QualType NewTy = NewElemTy; if (VectorSize.getBoolValue()) { - NewTy = Context.getVectorType(NewTy, VectorSize.getZExtValue(), - VectorType::GenericVector); + NewTy = S.Context.getVectorType(NewTy, VectorSize.getZExtValue(), + VectorType::GenericVector); } else if (const VectorType *OldVT = OldTy->getAs<VectorType>()) { // Complex machine mode does not support base vector types. if (ComplexMode) { - Diag(AttrLoc, diag::err_complex_mode_vector_type); + S.Diag(Attr.getLoc(), diag::err_complex_mode_vector_type); return; } - unsigned NumElements = Context.getTypeSize(OldElemTy) * + unsigned NumElements = S.Context.getTypeSize(OldElemTy) * OldVT->getNumElements() / - Context.getTypeSize(NewElemTy); + S.Context.getTypeSize(NewElemTy); NewTy = - Context.getVectorType(NewElemTy, NumElements, OldVT->getVectorKind()); + S.Context.getVectorType(NewElemTy, NumElements, OldVT->getVectorKind()); } if (NewTy.isNull()) { - Diag(AttrLoc, diag::err_mode_wrong_type); + S.Diag(Attr.getLoc(), diag::err_mode_wrong_type); return; } // Install the new type. if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) TD->setModedTypeSourceInfo(TD->getTypeSourceInfo(), NewTy); - else if (EnumDecl *ED = dyn_cast<EnumDecl>(D)) - ED->setIntegerType(NewTy); else cast<ValueDecl>(D)->setType(NewTy); - D->addAttr(::new (Context) - ModeAttr(AttrRange, Context, Name, SpellingListIndex)); + D->addAttr(::new (S.Context) + ModeAttr(Attr.getRange(), S.Context, Name, + Attr.getAttributeSpellingListIndex())); } static void handleNoDebugAttr(Sema &S, Decl *D, const AttributeList &Attr) { + if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { + if (!VD->hasGlobalStorage()) + S.Diag(Attr.getLoc(), + diag::warn_attribute_requires_functions_or_static_globals) + << Attr.getName(); + } else if (!isFunctionOrMethod(D)) { + S.Diag(Attr.getLoc(), + diag::warn_attribute_requires_functions_or_static_globals) + << Attr.getName(); + return; + } + D->addAttr(::new (S.Context) NoDebugAttr(Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex())); @@ -3870,38 +3606,6 @@ static void handleOptimizeNoneAttr(Sema &S, Decl *D, D->addAttr(Optnone); } -static void handleConstantAttr(Sema &S, Decl *D, const AttributeList &Attr) { - if (checkAttrMutualExclusion<CUDASharedAttr>(S, D, Attr.getRange(), - Attr.getName())) - return; - auto *VD = cast<VarDecl>(D); - if (!VD->hasGlobalStorage()) { - S.Diag(Attr.getLoc(), diag::err_cuda_nonglobal_constant); - return; - } - D->addAttr(::new (S.Context) CUDAConstantAttr( - Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex())); -} - -static void handleSharedAttr(Sema &S, Decl *D, const AttributeList &Attr) { - if (checkAttrMutualExclusion<CUDAConstantAttr>(S, D, Attr.getRange(), - Attr.getName())) - return; - auto *VD = cast<VarDecl>(D); - // extern __shared__ is only allowed on arrays with no length (e.g. - // "int x[]"). - if (VD->hasExternalStorage() && !isa<IncompleteArrayType>(VD->getType())) { - S.Diag(Attr.getLoc(), diag::err_cuda_extern_shared) << VD; - return; - } - if (S.getLangOpts().CUDA && VD->hasLocalStorage() && - S.CUDADiagIfHostCode(Attr.getLoc(), diag::err_cuda_host_shared) - << S.CurrentCUDATarget()) - return; - D->addAttr(::new (S.Context) CUDASharedAttr( - Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex())); -} - static void handleGlobalAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (checkAttrMutualExclusion<CUDADeviceAttr>(S, D, Attr.getRange(), Attr.getName()) || @@ -3918,21 +3622,11 @@ static void handleGlobalAttr(Sema &S, Decl *D, const AttributeList &Attr) { : FixItHint()); return; } - if (const auto *Method = dyn_cast<CXXMethodDecl>(FD)) { - if (Method->isInstance()) { - S.Diag(Method->getLocStart(), diag::err_kern_is_nonstatic_method) - << Method; - return; - } - S.Diag(Method->getLocStart(), diag::warn_kern_is_method) << Method; - } - // Only warn for "inline" when compiling for host, to cut down on noise. - if (FD->isInlineSpecified() && !S.getLangOpts().CUDAIsDevice) - S.Diag(FD->getLocStart(), diag::warn_kern_is_inline) << FD; D->addAttr(::new (S.Context) CUDAGlobalAttr(Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex())); + } static void handleGNUInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -3988,11 +3682,6 @@ static void handleCallConvAttr(Sema &S, Decl *D, const AttributeList &Attr) { PascalAttr(Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex())); return; - case AttributeList::AT_SwiftCall: - D->addAttr(::new (S.Context) - SwiftCallAttr(Attr.getRange(), S.Context, - Attr.getAttributeSpellingListIndex())); - return; case AttributeList::AT_VectorCall: D->addAttr(::new (S.Context) VectorCallAttr(Attr.getRange(), S.Context, @@ -4008,10 +3697,6 @@ static void handleCallConvAttr(Sema &S, Decl *D, const AttributeList &Attr) { SysVABIAttr(Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex())); return; - case AttributeList::AT_RegCall: - D->addAttr(::new (S.Context) RegCallAttr( - Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex())); - return; case AttributeList::AT_Pcs: { PcsAttr::PCSType PCS; switch (CC) { @@ -4035,14 +3720,7 @@ static void handleCallConvAttr(Sema &S, Decl *D, const AttributeList &Attr) { IntelOclBiccAttr(Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex())); return; - case AttributeList::AT_PreserveMost: - D->addAttr(::new (S.Context) PreserveMostAttr( - Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex())); - return; - case AttributeList::AT_PreserveAll: - D->addAttr(::new (S.Context) PreserveAllAttr( - Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex())); - return; + default: llvm_unreachable("unexpected attribute kind"); } @@ -4053,11 +3731,6 @@ bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC, if (attr.isInvalid()) return true; - if (attr.hasProcessingCache()) { - CC = (CallingConv) attr.getProcessingCache(); - return false; - } - unsigned ReqArgs = attr.getKind() == AttributeList::AT_Pcs ? 1 : 0; if (!checkAttributeNumArgs(*this, attr, ReqArgs)) { attr.setInvalid(); @@ -4071,9 +3744,7 @@ bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC, case AttributeList::AT_StdCall: CC = CC_X86StdCall; break; case AttributeList::AT_ThisCall: CC = CC_X86ThisCall; break; case AttributeList::AT_Pascal: CC = CC_X86Pascal; break; - case AttributeList::AT_SwiftCall: CC = CC_Swift; break; case AttributeList::AT_VectorCall: CC = CC_X86VectorCall; break; - case AttributeList::AT_RegCall: CC = CC_X86RegCall; break; case AttributeList::AT_MSABI: CC = Context.getTargetInfo().getTriple().isOSWindows() ? CC_C : CC_X86_64Win64; @@ -4101,8 +3772,6 @@ bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC, return true; } case AttributeList::AT_IntelOclBicc: CC = CC_IntelOclBicc; break; - case AttributeList::AT_PreserveMost: CC = CC_PreserveMost; break; - case AttributeList::AT_PreserveAll: CC = CC_PreserveAll; break; default: llvm_unreachable("unexpected attribute kind"); } @@ -4114,108 +3783,16 @@ bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC, // This convention is not valid for the target. Use the default function or // method calling convention. - bool IsCXXMethod = false, IsVariadic = false; - if (FD) { - IsCXXMethod = FD->isCXXInstanceMember(); - IsVariadic = FD->isVariadic(); - } - CC = Context.getDefaultCallingConvention(IsVariadic, IsCXXMethod); + TargetInfo::CallingConvMethodType MT = TargetInfo::CCMT_Unknown; + if (FD) + MT = FD->isCXXInstanceMember() ? TargetInfo::CCMT_Member : + TargetInfo::CCMT_NonMember; + CC = TI.getDefaultCallingConv(MT); } - attr.setProcessingCache((unsigned) CC); return false; } -/// Pointer-like types in the default address space. -static bool isValidSwiftContextType(QualType type) { - if (!type->hasPointerRepresentation()) - return type->isDependentType(); - return type->getPointeeType().getAddressSpace() == 0; -} - -/// Pointers and references in the default address space. -static bool isValidSwiftIndirectResultType(QualType type) { - if (auto ptrType = type->getAs<PointerType>()) { - type = ptrType->getPointeeType(); - } else if (auto refType = type->getAs<ReferenceType>()) { - type = refType->getPointeeType(); - } else { - return type->isDependentType(); - } - return type.getAddressSpace() == 0; -} - -/// Pointers and references to pointers in the default address space. -static bool isValidSwiftErrorResultType(QualType type) { - if (auto ptrType = type->getAs<PointerType>()) { - type = ptrType->getPointeeType(); - } else if (auto refType = type->getAs<ReferenceType>()) { - type = refType->getPointeeType(); - } else { - return type->isDependentType(); - } - if (!type.getQualifiers().empty()) - return false; - return isValidSwiftContextType(type); -} - -static void handleParameterABIAttr(Sema &S, Decl *D, const AttributeList &attr, - ParameterABI abi) { - S.AddParameterABIAttr(attr.getRange(), D, abi, - attr.getAttributeSpellingListIndex()); -} - -void Sema::AddParameterABIAttr(SourceRange range, Decl *D, ParameterABI abi, - unsigned spellingIndex) { - - QualType type = cast<ParmVarDecl>(D)->getType(); - - if (auto existingAttr = D->getAttr<ParameterABIAttr>()) { - if (existingAttr->getABI() != abi) { - Diag(range.getBegin(), diag::err_attributes_are_not_compatible) - << getParameterABISpelling(abi) << existingAttr; - Diag(existingAttr->getLocation(), diag::note_conflicting_attribute); - return; - } - } - - switch (abi) { - case ParameterABI::Ordinary: - llvm_unreachable("explicit attribute for ordinary parameter ABI?"); - - case ParameterABI::SwiftContext: - if (!isValidSwiftContextType(type)) { - Diag(range.getBegin(), diag::err_swift_abi_parameter_wrong_type) - << getParameterABISpelling(abi) - << /*pointer to pointer */ 0 << type; - } - D->addAttr(::new (Context) - SwiftContextAttr(range, Context, spellingIndex)); - return; - - case ParameterABI::SwiftErrorResult: - if (!isValidSwiftErrorResultType(type)) { - Diag(range.getBegin(), diag::err_swift_abi_parameter_wrong_type) - << getParameterABISpelling(abi) - << /*pointer to pointer */ 1 << type; - } - D->addAttr(::new (Context) - SwiftErrorResultAttr(range, Context, spellingIndex)); - return; - - case ParameterABI::SwiftIndirectResult: - if (!isValidSwiftIndirectResultType(type)) { - Diag(range.getBegin(), diag::err_swift_abi_parameter_wrong_type) - << getParameterABISpelling(abi) - << /*pointer*/ 0 << type; - } - D->addAttr(::new (Context) - SwiftIndirectResultAttr(range, Context, spellingIndex)); - return; - } - llvm_unreachable("bad parameter ABI attribute"); -} - /// Checks a regparm attribute, returning true if it is ill-formed and /// otherwise setting numParams to the appropriate value. bool Sema::CheckRegparmAttr(const AttributeList &Attr, unsigned &numParams) { @@ -4252,60 +3829,49 @@ bool Sema::CheckRegparmAttr(const AttributeList &Attr, unsigned &numParams) { return false; } -// Checks whether an argument of launch_bounds attribute is -// acceptable, performs implicit conversion to Rvalue, and returns -// non-nullptr Expr result on success. Otherwise, it returns nullptr -// and may output an error. -static Expr *makeLaunchBoundsArgExpr(Sema &S, Expr *E, - const CUDALaunchBoundsAttr &Attr, - const unsigned Idx) { +// Checks whether an argument of launch_bounds attribute is acceptable +// May output an error. +static bool checkLaunchBoundsArgument(Sema &S, Expr *E, + const CUDALaunchBoundsAttr &Attr, + const unsigned Idx) { + if (S.DiagnoseUnexpandedParameterPack(E)) - return nullptr; + return false; // Accept template arguments for now as they depend on something else. // We'll get to check them when they eventually get instantiated. if (E->isValueDependent()) - return E; + return true; llvm::APSInt I(64); if (!E->isIntegerConstantExpr(I, S.Context)) { S.Diag(E->getExprLoc(), diag::err_attribute_argument_n_type) << &Attr << Idx << AANT_ArgumentIntegerConstant << E->getSourceRange(); - return nullptr; + return false; } // Make sure we can fit it in 32 bits. if (!I.isIntN(32)) { S.Diag(E->getExprLoc(), diag::err_ice_too_large) << I.toString(10, false) << 32 << /* Unsigned */ 1; - return nullptr; + return false; } if (I < 0) S.Diag(E->getExprLoc(), diag::warn_attribute_argument_n_negative) << &Attr << Idx << E->getSourceRange(); - // We may need to perform implicit conversion of the argument. - InitializedEntity Entity = InitializedEntity::InitializeParameter( - S.Context, S.Context.getConstType(S.Context.IntTy), /*consume*/ false); - ExprResult ValArg = S.PerformCopyInitialization(Entity, SourceLocation(), E); - assert(!ValArg.isInvalid() && - "Unexpected PerformCopyInitialization() failure."); - - return ValArg.getAs<Expr>(); + return true; } void Sema::AddLaunchBoundsAttr(SourceRange AttrRange, Decl *D, Expr *MaxThreads, Expr *MinBlocks, unsigned SpellingListIndex) { CUDALaunchBoundsAttr TmpAttr(AttrRange, Context, MaxThreads, MinBlocks, SpellingListIndex); - MaxThreads = makeLaunchBoundsArgExpr(*this, MaxThreads, TmpAttr, 0); - if (MaxThreads == nullptr) + + if (!checkLaunchBoundsArgument(*this, MaxThreads, TmpAttr, 0)) return; - if (MinBlocks) { - MinBlocks = makeLaunchBoundsArgExpr(*this, MinBlocks, TmpAttr, 1); - if (MinBlocks == nullptr) - return; - } + if (MinBlocks && !checkLaunchBoundsArgument(*this, MinBlocks, TmpAttr, 1)) + return; D->addAttr(::new (Context) CUDALaunchBoundsAttr( AttrRange, Context, MaxThreads, MinBlocks, SpellingListIndex)); @@ -4411,7 +3977,6 @@ static bool isValidSubjectOfNSAttribute(Sema &S, QualType type) { type->isObjCObjectPointerType() || S.Context.isObjCNSObjectType(type); } - static bool isValidSubjectOfCFAttribute(Sema &S, QualType type) { return type->isDependentType() || type->isPointerType() || @@ -4419,49 +3984,36 @@ static bool isValidSubjectOfCFAttribute(Sema &S, QualType type) { } static void handleNSConsumedAttr(Sema &S, Decl *D, const AttributeList &Attr) { - S.AddNSConsumedAttr(Attr.getRange(), D, Attr.getAttributeSpellingListIndex(), - Attr.getKind() == AttributeList::AT_NSConsumed, - /*template instantiation*/ false); -} - -void Sema::AddNSConsumedAttr(SourceRange attrRange, Decl *D, - unsigned spellingIndex, bool isNSConsumed, - bool isTemplateInstantiation) { ParmVarDecl *param = cast<ParmVarDecl>(D); - bool typeOK; + bool typeOK, cf; - if (isNSConsumed) { - typeOK = isValidSubjectOfNSAttribute(*this, param->getType()); + if (Attr.getKind() == AttributeList::AT_NSConsumed) { + typeOK = isValidSubjectOfNSAttribute(S, param->getType()); + cf = false; } else { - typeOK = isValidSubjectOfCFAttribute(*this, param->getType()); + typeOK = isValidSubjectOfCFAttribute(S, param->getType()); + cf = true; } if (!typeOK) { - // These attributes are normally just advisory, but in ARC, ns_consumed - // is significant. Allow non-dependent code to contain inappropriate - // attributes even in ARC, but require template instantiations to be - // set up correctly. - Diag(D->getLocStart(), - (isTemplateInstantiation && isNSConsumed && - getLangOpts().ObjCAutoRefCount - ? diag::err_ns_attribute_wrong_parameter_type - : diag::warn_ns_attribute_wrong_parameter_type)) - << attrRange - << (isNSConsumed ? "ns_consumed" : "cf_consumed") - << (isNSConsumed ? /*objc pointers*/ 0 : /*cf pointers*/ 1); - return; - } - - if (isNSConsumed) - param->addAttr(::new (Context) - NSConsumedAttr(attrRange, Context, spellingIndex)); + S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_parameter_type) + << Attr.getRange() << Attr.getName() << cf; + return; + } + + if (cf) + param->addAttr(::new (S.Context) + CFConsumedAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); else - param->addAttr(::new (Context) - CFConsumedAttr(attrRange, Context, spellingIndex)); + param->addAttr(::new (S.Context) + NSConsumedAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleNSReturnsRetainedAttr(Sema &S, Decl *D, const AttributeList &Attr) { + QualType returnType; if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) @@ -4735,9 +4287,10 @@ static void handleObjCRuntimeName(Sema &S, Decl *D, Attr.getAttributeSpellingListIndex())); } -// When a user wants to use objc_boxable with a union or struct -// but they don't have access to the declaration (legacy/third-party code) -// then they can 'enable' this feature with a typedef: +// when a user wants to use objc_boxable with a union or struct +// but she doesn't have access to the declaration (legacy/third-party code) +// then she can 'enable' this feature via trick with a typedef +// e.g.: // typedef struct __attribute((objc_boxable)) legacy_struct legacy_struct; static void handleObjCBoxable(Sema &S, Decl *D, const AttributeList &Attr) { bool notify = false; @@ -4815,19 +4368,6 @@ static void handleObjCPreciseLifetimeAttr(Sema &S, Decl *D, // Microsoft specific attribute handlers. //===----------------------------------------------------------------------===// -UuidAttr *Sema::mergeUuidAttr(Decl *D, SourceRange Range, - unsigned AttrSpellingListIndex, StringRef Uuid) { - if (const auto *UA = D->getAttr<UuidAttr>()) { - if (UA->getGuid().equals_lower(Uuid)) - return nullptr; - Diag(UA->getLocation(), diag::err_mismatched_uuid); - Diag(Range.getBegin(), diag::note_previous_uuid); - D->dropAttr<UuidAttr>(); - } - - return ::new (Context) UuidAttr(Range, Context, Uuid, AttrSpellingListIndex); -} - static void handleUuidAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (!S.LangOpts.CPlusPlus) { S.Diag(Attr.getLoc(), diag::err_attribute_not_supported_in_lang) @@ -4835,6 +4375,12 @@ static void handleUuidAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } + if (!isa<CXXRecordDecl>(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedClass; + return; + } + StringRef StrRef; SourceLocation LiteralLoc; if (!S.checkStringLiteralArgumentAttr(Attr, 0, StrRef, &LiteralLoc)) @@ -4863,10 +4409,8 @@ static void handleUuidAttr(Sema &S, Decl *D, const AttributeList &Attr) { } } - UuidAttr *UA = S.mergeUuidAttr(D, Attr.getRange(), - Attr.getAttributeSpellingListIndex(), StrRef); - if (UA) - D->addAttr(UA); + D->addAttr(::new (S.Context) UuidAttr(Attr.getRange(), S.Context, StrRef, + Attr.getAttributeSpellingListIndex())); } static void handleMSInheritanceAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -4879,10 +4423,8 @@ static void handleMSInheritanceAttr(Sema &S, Decl *D, const AttributeList &Attr) D, Attr.getRange(), /*BestCase=*/true, Attr.getAttributeSpellingListIndex(), (MSInheritanceAttr::Spelling)Attr.getSemanticSpelling()); - if (IA) { + if (IA) D->addAttr(IA); - S.Consumer.AssignInheritanceModel(cast<CXXRecordDecl>(D)); - } } static void handleDeclspecThreadAttr(Sema &S, Decl *D, @@ -4904,38 +4446,6 @@ static void handleDeclspecThreadAttr(Sema &S, Decl *D, Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex())); } -static void handleAbiTagAttr(Sema &S, Decl *D, const AttributeList &Attr) { - SmallVector<StringRef, 4> Tags; - for (unsigned I = 0, E = Attr.getNumArgs(); I != E; ++I) { - StringRef Tag; - if (!S.checkStringLiteralArgumentAttr(Attr, I, Tag)) - return; - Tags.push_back(Tag); - } - - if (const auto *NS = dyn_cast<NamespaceDecl>(D)) { - if (!NS->isInline()) { - S.Diag(Attr.getLoc(), diag::warn_attr_abi_tag_namespace) << 0; - return; - } - if (NS->isAnonymousNamespace()) { - S.Diag(Attr.getLoc(), diag::warn_attr_abi_tag_namespace) << 1; - return; - } - if (Attr.getNumArgs() == 0) - Tags.push_back(NS->getName()); - } else if (!checkAttributeAtLeastNumArgs(S, Attr, 1)) - return; - - // Store tags sorted and without duplicates. - std::sort(Tags.begin(), Tags.end()); - Tags.erase(std::unique(Tags.begin(), Tags.end()), Tags.end()); - - D->addAttr(::new (S.Context) - AbiTagAttr(Attr.getRange(), S.Context, Tags.data(), Tags.size(), - Attr.getAttributeSpellingListIndex())); -} - static void handleARMInterruptAttr(Sema &S, Decl *D, const AttributeList &Attr) { // Check the attribute arguments. @@ -5060,171 +4570,42 @@ static void handleMipsInterruptAttr(Sema &S, Decl *D, Attr.getLoc(), S.Context, Kind, Attr.getAttributeSpellingListIndex())); } -static void handleAnyX86InterruptAttr(Sema &S, Decl *D, - const AttributeList &Attr) { - // Semantic checks for a function with the 'interrupt' attribute. - // a) Must be a function. - // b) Must have the 'void' return type. - // c) Must take 1 or 2 arguments. - // d) The 1st argument must be a pointer. - // e) The 2nd argument (if any) must be an unsigned integer. - if (!isFunctionOrMethod(D) || !hasFunctionProto(D) || isInstanceMethod(D) || - CXXMethodDecl::isStaticOverloadedOperator( - cast<NamedDecl>(D)->getDeclName().getCXXOverloadedOperator())) { - S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << ExpectedFunctionWithProtoType; - return; - } - // Interrupt handler must have void return type. - if (!getFunctionOrMethodResultType(D)->isVoidType()) { - S.Diag(getFunctionOrMethodResultSourceRange(D).getBegin(), - diag::err_anyx86_interrupt_attribute) - << (S.Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86 - ? 0 - : 1) - << 0; - return; - } - // Interrupt handler must have 1 or 2 parameters. - unsigned NumParams = getFunctionOrMethodNumParams(D); - if (NumParams < 1 || NumParams > 2) { - S.Diag(D->getLocStart(), diag::err_anyx86_interrupt_attribute) - << (S.Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86 - ? 0 - : 1) - << 1; - return; - } - // The first argument must be a pointer. - if (!getFunctionOrMethodParamType(D, 0)->isPointerType()) { - S.Diag(getFunctionOrMethodParamRange(D, 0).getBegin(), - diag::err_anyx86_interrupt_attribute) - << (S.Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86 - ? 0 - : 1) - << 2; - return; - } - // The second argument, if present, must be an unsigned integer. - unsigned TypeSize = - S.Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86_64 - ? 64 - : 32; - if (NumParams == 2 && - (!getFunctionOrMethodParamType(D, 1)->isUnsignedIntegerType() || - S.Context.getTypeSize(getFunctionOrMethodParamType(D, 1)) != TypeSize)) { - S.Diag(getFunctionOrMethodParamRange(D, 1).getBegin(), - diag::err_anyx86_interrupt_attribute) - << (S.Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86 - ? 0 - : 1) - << 3 << S.Context.getIntTypeForBitwidth(TypeSize, /*Signed=*/false); - return; - } - D->addAttr(::new (S.Context) AnyX86InterruptAttr( - Attr.getLoc(), S.Context, Attr.getAttributeSpellingListIndex())); - D->addAttr(UsedAttr::CreateImplicit(S.Context)); -} - static void handleInterruptAttr(Sema &S, Decl *D, const AttributeList &Attr) { // Dispatch the interrupt attribute based on the current target. - switch (S.Context.getTargetInfo().getTriple().getArch()) { - case llvm::Triple::msp430: + if (S.Context.getTargetInfo().getTriple().getArch() == llvm::Triple::msp430) handleMSP430InterruptAttr(S, D, Attr); - break; - case llvm::Triple::mipsel: - case llvm::Triple::mips: + else if (S.Context.getTargetInfo().getTriple().getArch() == + llvm::Triple::mipsel || + S.Context.getTargetInfo().getTriple().getArch() == + llvm::Triple::mips) handleMipsInterruptAttr(S, D, Attr); - break; - case llvm::Triple::x86: - case llvm::Triple::x86_64: - handleAnyX86InterruptAttr(S, D, Attr); - break; - default: + else handleARMInterruptAttr(S, D, Attr); - break; - } -} - -static void handleAMDGPUFlatWorkGroupSizeAttr(Sema &S, Decl *D, - const AttributeList &Attr) { - uint32_t Min = 0; - Expr *MinExpr = Attr.getArgAsExpr(0); - if (!checkUInt32Argument(S, Attr, MinExpr, Min)) - return; - - uint32_t Max = 0; - Expr *MaxExpr = Attr.getArgAsExpr(1); - if (!checkUInt32Argument(S, Attr, MaxExpr, Max)) - return; - - if (Min == 0 && Max != 0) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_invalid) - << Attr.getName() << 0; - return; - } - if (Min > Max) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_invalid) - << Attr.getName() << 1; - return; - } - - D->addAttr(::new (S.Context) - AMDGPUFlatWorkGroupSizeAttr(Attr.getLoc(), S.Context, Min, Max, - Attr.getAttributeSpellingListIndex())); -} - -static void handleAMDGPUWavesPerEUAttr(Sema &S, Decl *D, - const AttributeList &Attr) { - uint32_t Min = 0; - Expr *MinExpr = Attr.getArgAsExpr(0); - if (!checkUInt32Argument(S, Attr, MinExpr, Min)) - return; - - uint32_t Max = 0; - if (Attr.getNumArgs() == 2) { - Expr *MaxExpr = Attr.getArgAsExpr(1); - if (!checkUInt32Argument(S, Attr, MaxExpr, Max)) - return; - } - - if (Min == 0 && Max != 0) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_invalid) - << Attr.getName() << 0; - return; - } - if (Max != 0 && Min > Max) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_invalid) - << Attr.getName() << 1; - return; - } - - D->addAttr(::new (S.Context) - AMDGPUWavesPerEUAttr(Attr.getLoc(), S.Context, Min, Max, - Attr.getAttributeSpellingListIndex())); } -static void handleAMDGPUNumSGPRAttr(Sema &S, Decl *D, +static void handleAMDGPUNumVGPRAttr(Sema &S, Decl *D, const AttributeList &Attr) { - uint32_t NumSGPR = 0; - Expr *NumSGPRExpr = Attr.getArgAsExpr(0); - if (!checkUInt32Argument(S, Attr, NumSGPRExpr, NumSGPR)) + uint32_t NumRegs; + Expr *NumRegsExpr = static_cast<Expr *>(Attr.getArgAsExpr(0)); + if (!checkUInt32Argument(S, Attr, NumRegsExpr, NumRegs)) return; D->addAttr(::new (S.Context) - AMDGPUNumSGPRAttr(Attr.getLoc(), S.Context, NumSGPR, + AMDGPUNumVGPRAttr(Attr.getLoc(), S.Context, + NumRegs, Attr.getAttributeSpellingListIndex())); } -static void handleAMDGPUNumVGPRAttr(Sema &S, Decl *D, +static void handleAMDGPUNumSGPRAttr(Sema &S, Decl *D, const AttributeList &Attr) { - uint32_t NumVGPR = 0; - Expr *NumVGPRExpr = Attr.getArgAsExpr(0); - if (!checkUInt32Argument(S, Attr, NumVGPRExpr, NumVGPR)) + uint32_t NumRegs; + Expr *NumRegsExpr = static_cast<Expr *>(Attr.getArgAsExpr(0)); + if (!checkUInt32Argument(S, Attr, NumRegsExpr, NumRegs)) return; D->addAttr(::new (S.Context) - AMDGPUNumVGPRAttr(Attr.getLoc(), S.Context, NumVGPR, + AMDGPUNumSGPRAttr(Attr.getLoc(), S.Context, + NumRegs, Attr.getAttributeSpellingListIndex())); } @@ -5253,24 +4634,6 @@ static void handleX86ForceAlignArgPointerAttr(Sema &S, Decl *D, Attr.getAttributeSpellingListIndex())); } -static void handleLayoutVersion(Sema &S, Decl *D, const AttributeList &Attr) { - uint32_t Version; - Expr *VersionExpr = static_cast<Expr *>(Attr.getArgAsExpr(0)); - if (!checkUInt32Argument(S, Attr, Attr.getArgAsExpr(0), Version)) - return; - - // TODO: Investigate what happens with the next major version of MSVC. - if (Version != LangOptions::MSVC2015) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds) - << Attr.getName() << Version << VersionExpr->getSourceRange(); - return; - } - - D->addAttr(::new (S.Context) - LayoutVersionAttr(Attr.getRange(), S.Context, Version, - Attr.getAttributeSpellingListIndex())); -} - DLLImportAttr *Sema::mergeDLLImportAttr(Decl *D, SourceRange Range, unsigned AttrSpellingListIndex) { if (D->hasAttr<DLLExportAttr>()) { @@ -5464,40 +4827,19 @@ static void handleDeprecatedAttr(Sema &S, Decl *D, const AttributeList &Attr) { } } - // Handle the cases where the attribute has a text message. - StringRef Str, Replacement; - if (Attr.isArgExpr(0) && Attr.getArgAsExpr(0) && - !S.checkStringLiteralArgumentAttr(Attr, 0, Str)) - return; - - // Only support a single optional message for Declspec and CXX11. - if (Attr.isDeclspecAttribute() || Attr.isCXX11Attribute()) - checkAttributeAtMostNumArgs(S, Attr, 1); - else if (Attr.isArgExpr(1) && Attr.getArgAsExpr(1) && - !S.checkStringLiteralArgumentAttr(Attr, 1, Replacement)) - return; - if (!S.getLangOpts().CPlusPlus14) if (Attr.isCXX11Attribute() && !(Attr.hasScope() && Attr.getScopeName()->isStr("gnu"))) - S.Diag(Attr.getLoc(), diag::ext_cxx14_attr) << Attr.getName(); - - D->addAttr(::new (S.Context) - DeprecatedAttr(Attr.getRange(), S.Context, Str, Replacement, - Attr.getAttributeSpellingListIndex())); -} + S.Diag(Attr.getLoc(), diag::ext_deprecated_attr_is_a_cxx14_extension); -static bool isGlobalVar(const Decl *D) { - if (const auto *S = dyn_cast<VarDecl>(D)) - return S->hasGlobalStorage(); - return false; + handleAttrWithMessage<DeprecatedAttr>(S, D, Attr); } static void handleNoSanitizeAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (!checkAttributeAtLeastNumArgs(S, Attr, 1)) return; - std::vector<StringRef> Sanitizers; + std::vector<std::string> Sanitizers; for (unsigned I = 0, E = Attr.getNumArgs(); I != E; ++I) { StringRef SanitizerName; @@ -5508,9 +4850,7 @@ static void handleNoSanitizeAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (parseSanitizerValue(SanitizerName, /*AllowGroups=*/true) == 0) S.Diag(LiteralLoc, diag::warn_unknown_sanitizer_ignored) << SanitizerName; - else if (isGlobalVar(D) && SanitizerName != "address") - S.Diag(D->getLocation(), diag::err_attribute_wrong_decl_type) - << Attr.getName() << ExpectedFunctionOrMethod; + Sanitizers.push_back(SanitizerName); } @@ -5523,14 +4863,12 @@ static void handleNoSanitizeSpecificAttr(Sema &S, Decl *D, const AttributeList &Attr) { StringRef AttrName = Attr.getName()->getName(); normalizeName(AttrName); - StringRef SanitizerName = llvm::StringSwitch<StringRef>(AttrName) - .Case("no_address_safety_analysis", "address") - .Case("no_sanitize_address", "address") - .Case("no_sanitize_thread", "thread") - .Case("no_sanitize_memory", "memory"); - if (isGlobalVar(D) && SanitizerName != "address") - S.Diag(D->getLocation(), diag::err_attribute_wrong_decl_type) - << Attr.getName() << ExpectedFunction; + std::string SanitizerName = + llvm::StringSwitch<std::string>(AttrName) + .Case("no_address_safety_analysis", "address") + .Case("no_sanitize_address", "address") + .Case("no_sanitize_thread", "thread") + .Case("no_sanitize_memory", "memory"); D->addAttr(::new (S.Context) NoSanitizeAttr(Attr.getRange(), S.Context, &SanitizerName, 1, Attr.getAttributeSpellingListIndex())); @@ -5544,15 +4882,6 @@ static void handleInternalLinkageAttr(Sema &S, Decl *D, D->addAttr(Internal); } -static void handleOpenCLNoSVMAttr(Sema &S, Decl *D, const AttributeList &Attr) { - if (S.LangOpts.OpenCLVersion != 200) - S.Diag(Attr.getLoc(), diag::err_attribute_requires_opencl_version) - << Attr.getName() << "2.0" << 0; - else - S.Diag(Attr.getLoc(), diag::warn_opencl_attr_deprecated_ignored) - << Attr.getName() << "2.0"; -} - /// Handles semantic checking for features that are common to all attributes, /// such as checking whether a parameter was properly specified, or the correct /// number of arguments were passed, etc. @@ -5594,40 +4923,6 @@ static bool handleCommonAttributeFeatures(Sema &S, Scope *scope, Decl *D, return false; } -static void handleOpenCLAccessAttr(Sema &S, Decl *D, - const AttributeList &Attr) { - if (D->isInvalidDecl()) - return; - - // Check if there is only one access qualifier. - if (D->hasAttr<OpenCLAccessAttr>()) { - S.Diag(Attr.getLoc(), diag::err_opencl_multiple_access_qualifiers) - << D->getSourceRange(); - D->setInvalidDecl(true); - return; - } - - // OpenCL v2.0 s6.6 - read_write can be used for image types to specify that an - // image object can be read and written. - // OpenCL v2.0 s6.13.6 - A kernel cannot read from and write to the same pipe - // object. Using the read_write (or __read_write) qualifier with the pipe - // qualifier is a compilation error. - if (const ParmVarDecl *PDecl = dyn_cast<ParmVarDecl>(D)) { - const Type *DeclTy = PDecl->getType().getCanonicalType().getTypePtr(); - if (Attr.getName()->getName().find("read_write") != StringRef::npos) { - if (S.getLangOpts().OpenCLVersion < 200 || DeclTy->isPipeType()) { - S.Diag(Attr.getLoc(), diag::err_opencl_invalid_read_write) - << Attr.getName() << PDecl->getType() << DeclTy->isImageType(); - D->setInvalidDecl(true); - return; - } - } - } - - D->addAttr(::new (S.Context) OpenCLAccessAttr( - Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex())); -} - //===----------------------------------------------------------------------===// // Top Level Sema Entry Points //===----------------------------------------------------------------------===// @@ -5663,13 +4958,8 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, switch (Attr.getKind()) { default: - if (!Attr.isStmtAttr()) { - // Type attributes are handled elsewhere; silently move on. - assert(Attr.isTypeAttr() && "Non-type attribute not handled"); - break; - } - S.Diag(Attr.getLoc(), diag::err_stmt_attribute_invalid_on_decl) - << Attr.getName() << D->getLocation(); + // Type attributes are handled elsewhere; silently move on. + assert(Attr.isTypeAttr() && "Non-type attribute not handled"); break; case AttributeList::AT_Interrupt: handleInterruptAttr(S, D, Attr); @@ -5688,18 +4978,12 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_NoMips16: handleSimpleAttribute<NoMips16Attr>(S, D, Attr); break; - case AttributeList::AT_AMDGPUFlatWorkGroupSize: - handleAMDGPUFlatWorkGroupSizeAttr(S, D, Attr); - break; - case AttributeList::AT_AMDGPUWavesPerEU: - handleAMDGPUWavesPerEUAttr(S, D, Attr); + case AttributeList::AT_AMDGPUNumVGPR: + handleAMDGPUNumVGPRAttr(S, D, Attr); break; case AttributeList::AT_AMDGPUNumSGPR: handleAMDGPUNumSGPRAttr(S, D, Attr); break; - case AttributeList::AT_AMDGPUNumVGPR: - handleAMDGPUNumVGPRAttr(S, D, Attr); - break; case AttributeList::AT_IBAction: handleSimpleAttribute<IBActionAttr>(S, D, Attr); break; @@ -5709,9 +4993,6 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_IBOutletCollection: handleIBOutletCollection(S, D, Attr); break; - case AttributeList::AT_IFunc: - handleIFuncAttr(S, D, Attr); - break; case AttributeList::AT_Alias: handleAliasAttr(S, D, Attr); break; @@ -5721,9 +5002,6 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_AlignValue: handleAlignValueAttr(S, D, Attr); break; - case AttributeList::AT_AllocSize: - handleAllocSizeAttr(S, D, Attr); - break; case AttributeList::AT_AlwaysInline: handleAlwaysInlineAttr(S, D, Attr); break; @@ -5746,7 +5024,8 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, handleCommonAttr(S, D, Attr); break; case AttributeList::AT_CUDAConstant: - handleConstantAttr(S, D, Attr); + handleSimpleAttributeWithExclusions<CUDAConstantAttr, CUDASharedAttr>(S, D, + Attr); break; case AttributeList::AT_PassObjectSize: handlePassObjectSizeAttr(S, D, Attr); @@ -5766,9 +5045,6 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_EnableIf: handleEnableIfAttr(S, D, Attr); break; - case AttributeList::AT_DiagnoseIf: - handleDiagnoseIfAttr(S, D, Attr); - break; case AttributeList::AT_ExtVectorType: handleExtVectorTypeAttr(S, scope, D, Attr); break; @@ -5859,50 +5135,59 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, handleSimpleAttribute<NoThrowAttr>(S, D, Attr); break; case AttributeList::AT_CUDAShared: - handleSharedAttr(S, D, Attr); + handleSimpleAttributeWithExclusions<CUDASharedAttr, CUDAConstantAttr>(S, D, + Attr); break; case AttributeList::AT_VecReturn: handleVecReturnAttr(S, D, Attr); break; + case AttributeList::AT_ObjCOwnership: handleObjCOwnershipAttr(S, D, Attr); break; case AttributeList::AT_ObjCPreciseLifetime: handleObjCPreciseLifetimeAttr(S, D, Attr); break; + case AttributeList::AT_ObjCReturnsInnerPointer: handleObjCReturnsInnerPointerAttr(S, D, Attr); break; + case AttributeList::AT_ObjCRequiresSuper: handleObjCRequiresSuperAttr(S, D, Attr); break; + case AttributeList::AT_ObjCBridge: handleObjCBridgeAttr(S, scope, D, Attr); break; + case AttributeList::AT_ObjCBridgeMutable: handleObjCBridgeMutableAttr(S, scope, D, Attr); break; + case AttributeList::AT_ObjCBridgeRelated: handleObjCBridgeRelatedAttr(S, scope, D, Attr); break; + case AttributeList::AT_ObjCDesignatedInitializer: handleObjCDesignatedInitializer(S, D, Attr); break; + case AttributeList::AT_ObjCRuntimeName: handleObjCRuntimeName(S, D, Attr); break; - case AttributeList::AT_ObjCRuntimeVisible: - handleSimpleAttribute<ObjCRuntimeVisibleAttr>(S, D, Attr); - break; + case AttributeList::AT_ObjCBoxable: handleObjCBoxable(S, D, Attr); break; + case AttributeList::AT_CFAuditedTransfer: handleCFAuditedTransferAttr(S, D, Attr); break; case AttributeList::AT_CFUnknownTransfer: handleCFUnknownTransferAttr(S, D, Attr); break; + case AttributeList::AT_CFConsumed: case AttributeList::AT_NSConsumed: handleNSConsumedAttr(S, D, Attr); @@ -5910,6 +5195,7 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_NSConsumesSelf: handleSimpleAttribute<NSConsumesSelfAttr>(S, D, Attr); break; + case AttributeList::AT_NSReturnsAutoreleased: case AttributeList::AT_NSReturnsNotRetained: case AttributeList::AT_CFReturnsNotRetained: @@ -5926,12 +5212,11 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_VecTypeHint: handleVecTypeHint(S, D, Attr); break; - case AttributeList::AT_RequireConstantInit: - handleSimpleAttribute<RequireConstantInitAttr>(S, D, Attr); - break; + case AttributeList::AT_InitPriority: handleInitPriorityAttr(S, D, Attr); break; + case AttributeList::AT_Packed: handlePackedAttr(S, D, Attr); break; @@ -5950,9 +5235,6 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_ObjCRootClass: handleSimpleAttribute<ObjCRootClassAttr>(S, D, Attr); break; - case AttributeList::AT_ObjCSubclassingRestricted: - handleSimpleAttribute<ObjCSubclassingRestrictedAttr>(S, D, Attr); - break; case AttributeList::AT_ObjCExplicitProtocolImpl: handleObjCSuppresProtocolAttr(S, D, Attr); break; @@ -5960,7 +5242,7 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, handleSimpleAttribute<ObjCRequiresPropertyDefsAttr>(S, D, Attr); break; case AttributeList::AT_Unused: - handleUnusedAttr(S, D, Attr); + handleSimpleAttribute<UnusedAttr>(S, D, Attr); break; case AttributeList::AT_ReturnsTwice: handleSimpleAttribute<ReturnsTwiceAttr>(S, D, Attr); @@ -6031,9 +5313,6 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_NoDuplicate: handleSimpleAttribute<NoDuplicateAttr>(S, D, Attr); break; - case AttributeList::AT_Convergent: - handleSimpleAttribute<ConvergentAttr>(S, D, Attr); - break; case AttributeList::AT_NoInline: handleSimpleAttribute<NoInlineAttr>(S, D, Attr); break; @@ -6045,49 +5324,24 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_FastCall: case AttributeList::AT_ThisCall: case AttributeList::AT_Pascal: - case AttributeList::AT_RegCall: - case AttributeList::AT_SwiftCall: case AttributeList::AT_VectorCall: case AttributeList::AT_MSABI: case AttributeList::AT_SysVABI: case AttributeList::AT_Pcs: case AttributeList::AT_IntelOclBicc: - case AttributeList::AT_PreserveMost: - case AttributeList::AT_PreserveAll: handleCallConvAttr(S, D, Attr); break; case AttributeList::AT_OpenCLKernel: handleSimpleAttribute<OpenCLKernelAttr>(S, D, Attr); break; - case AttributeList::AT_OpenCLAccess: - handleOpenCLAccessAttr(S, D, Attr); - break; - case AttributeList::AT_OpenCLNoSVM: - handleOpenCLNoSVMAttr(S, D, Attr); - break; - case AttributeList::AT_SwiftContext: - handleParameterABIAttr(S, D, Attr, ParameterABI::SwiftContext); - break; - case AttributeList::AT_SwiftErrorResult: - handleParameterABIAttr(S, D, Attr, ParameterABI::SwiftErrorResult); - break; - case AttributeList::AT_SwiftIndirectResult: - handleParameterABIAttr(S, D, Attr, ParameterABI::SwiftIndirectResult); + case AttributeList::AT_OpenCLImageAccess: + handleSimpleAttribute<OpenCLImageAccessAttr>(S, D, Attr); break; case AttributeList::AT_InternalLinkage: handleInternalLinkageAttr(S, D, Attr); break; - case AttributeList::AT_LTOVisibilityPublic: - handleSimpleAttribute<LTOVisibilityPublicAttr>(S, D, Attr); - break; // Microsoft attributes: - case AttributeList::AT_EmptyBases: - handleSimpleAttribute<EmptyBasesAttr>(S, D, Attr); - break; - case AttributeList::AT_LayoutVersion: - handleLayoutVersion(S, D, Attr); - break; case AttributeList::AT_MSNoVTable: handleSimpleAttribute<MSNoVTableAttr>(S, D, Attr); break; @@ -6107,10 +5361,6 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, handleDeclspecThreadAttr(S, D, Attr); break; - case AttributeList::AT_AbiTag: - handleAbiTagAttr(S, D, Attr); - break; - // Thread safety attributes: case AttributeList::AT_AssertExclusiveLock: handleAssertExclusiveLockAttr(S, D, Attr); @@ -6216,13 +5466,6 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_TypeTagForDatatype: handleTypeTagForDatatypeAttr(S, D, Attr); break; - case AttributeList::AT_RenderScriptKernel: - handleSimpleAttribute<RenderScriptKernelAttr>(S, D, Attr); - break; - // XRay attributes. - case AttributeList::AT_XRayInstrument: - handleSimpleAttribute<XRayInstrumentAttr>(S, D, Attr); - break; } } @@ -6262,11 +5505,7 @@ void Sema::ProcessDeclAttributeList(Scope *S, Decl *D, } else if (Attr *A = D->getAttr<VecTypeHintAttr>()) { Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A; D->setInvalidDecl(); - } else if (Attr *A = D->getAttr<AMDGPUFlatWorkGroupSizeAttr>()) { - Diag(D->getLocation(), diag::err_attribute_wrong_decl_type) - << A << ExpectedKernelFunction; - D->setInvalidDecl(); - } else if (Attr *A = D->getAttr<AMDGPUWavesPerEUAttr>()) { + } else if (Attr *A = D->getAttr<AMDGPUNumVGPRAttr>()) { Diag(D->getLocation(), diag::err_attribute_wrong_decl_type) << A << ExpectedKernelFunction; D->setInvalidDecl(); @@ -6274,10 +5513,6 @@ void Sema::ProcessDeclAttributeList(Scope *S, Decl *D, Diag(D->getLocation(), diag::err_attribute_wrong_decl_type) << A << ExpectedKernelFunction; D->setInvalidDecl(); - } else if (Attr *A = D->getAttr<AMDGPUNumVGPRAttr>()) { - Diag(D->getLocation(), diag::err_attribute_wrong_decl_type) - << A << ExpectedKernelFunction; - D->setInvalidDecl(); } } } @@ -6509,100 +5744,32 @@ static void handleDelayedForbiddenType(Sema &S, DelayedDiagnostic &diag, diag.Triggered = true; } -static const AvailabilityAttr *getAttrForPlatform(ASTContext &Context, - const Decl *D) { - // Check each AvailabilityAttr to find the one for this platform. - for (const auto *A : D->attrs()) { - if (const auto *Avail = dyn_cast<AvailabilityAttr>(A)) { - // FIXME: this is copied from CheckAvailability. We should try to - // de-duplicate. - - // Check if this is an App Extension "platform", and if so chop off - // the suffix for matching with the actual platform. - StringRef ActualPlatform = Avail->getPlatform()->getName(); - StringRef RealizedPlatform = ActualPlatform; - if (Context.getLangOpts().AppExt) { - size_t suffix = RealizedPlatform.rfind("_app_extension"); - if (suffix != StringRef::npos) - RealizedPlatform = RealizedPlatform.slice(0, suffix); - } - - StringRef TargetPlatform = Context.getTargetInfo().getPlatformName(); - - // Match the platform name. - if (RealizedPlatform == TargetPlatform) - return Avail; - } - } - return nullptr; -} - -/// \brief whether we should emit a diagnostic for \c K and \c DeclVersion in -/// the context of \c Ctx. For example, we should emit an unavailable diagnostic -/// in a deprecated context, but not the other way around. -static bool ShouldDiagnoseAvailabilityInContext(Sema &S, AvailabilityResult K, - VersionTuple DeclVersion, - Decl *Ctx) { - assert(K != AR_Available && "Expected an unavailable declaration here!"); - // Checks if we should emit the availability diagnostic in the context of C. - auto CheckContext = [&](const Decl *C) { - if (K == AR_NotYetIntroduced) { - if (const AvailabilityAttr *AA = getAttrForPlatform(S.Context, C)) - if (AA->getIntroduced() >= DeclVersion) - return true; - } else if (K == AR_Deprecated) - if (C->isDeprecated()) - return true; - - if (C->isUnavailable()) +static bool isDeclDeprecated(Decl *D) { + do { + if (D->isDeprecated()) return true; - return false; - }; - - // FIXME: This is a temporary workaround! Some existing Apple headers depends - // on nested declarations in an @interface having the availability of the - // interface when they really shouldn't: they are members of the enclosing - // context, and can referenced from there. - if (S.OriginalLexicalContext && cast<Decl>(S.OriginalLexicalContext) != Ctx) { - auto *OrigCtx = cast<Decl>(S.OriginalLexicalContext); - if (CheckContext(OrigCtx)) - return false; - - // An implementation implicitly has the availability of the interface. - if (auto *CatOrImpl = dyn_cast<ObjCImplDecl>(OrigCtx)) { - if (const ObjCInterfaceDecl *Interface = CatOrImpl->getClassInterface()) - if (CheckContext(Interface)) - return false; - } // A category implicitly has the availability of the interface. - else if (auto *CatD = dyn_cast<ObjCCategoryDecl>(OrigCtx)) + if (const ObjCCategoryDecl *CatD = dyn_cast<ObjCCategoryDecl>(D)) if (const ObjCInterfaceDecl *Interface = CatD->getClassInterface()) - if (CheckContext(Interface)) - return false; - } + return Interface->isDeprecated(); + } while ((D = cast_or_null<Decl>(D->getDeclContext()))); + return false; +} +static bool isDeclUnavailable(Decl *D) { do { - if (CheckContext(Ctx)) - return false; - - // An implementation implicitly has the availability of the interface. - if (auto *CatOrImpl = dyn_cast<ObjCImplDecl>(Ctx)) { - if (const ObjCInterfaceDecl *Interface = CatOrImpl->getClassInterface()) - if (CheckContext(Interface)) - return false; - } + if (D->isUnavailable()) + return true; // A category implicitly has the availability of the interface. - else if (auto *CatD = dyn_cast<ObjCCategoryDecl>(Ctx)) + if (const ObjCCategoryDecl *CatD = dyn_cast<ObjCCategoryDecl>(D)) if (const ObjCInterfaceDecl *Interface = CatD->getClassInterface()) - if (CheckContext(Interface)) - return false; - } while ((Ctx = cast_or_null<Decl>(Ctx->getDeclContext()))); - - return true; + return Interface->isUnavailable(); + } while ((D = cast_or_null<Decl>(D->getDeclContext()))); + return false; } -static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K, +static void DoEmitAvailabilityWarning(Sema &S, Sema::AvailabilityDiagnostic K, Decl *Ctx, const NamedDecl *D, StringRef Message, SourceLocation Loc, const ObjCInterfaceDecl *UnknownObjCClass, @@ -6618,15 +5785,11 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K, // Matches diag::note_availability_specified_here. unsigned available_here_select_kind; - VersionTuple DeclVersion; - if (const AvailabilityAttr *AA = getAttrForPlatform(S.Context, D)) - DeclVersion = AA->getIntroduced(); - - if (!ShouldDiagnoseAvailabilityInContext(S, K, DeclVersion, Ctx)) - return; - + // Don't warn if our current context is deprecated or unavailable. switch (K) { - case AR_Deprecated: + case Sema::AD_Deprecation: + if (isDeclDeprecated(Ctx) || isDeclUnavailable(Ctx)) + return; diag = !ObjCPropertyAccess ? diag::warn_deprecated : diag::warn_property_method_deprecated; diag_message = diag::warn_deprecated_message; @@ -6635,7 +5798,9 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K, available_here_select_kind = /* deprecated */ 2; break; - case AR_Unavailable: + case Sema::AD_Unavailable: + if (isDeclUnavailable(Ctx)) + return; diag = !ObjCPropertyAccess ? diag::err_unavailable : diag::err_property_method_unavailable; diag_message = diag::err_unavailable_message; @@ -6685,89 +5850,50 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K, } } } + break; - case AR_NotYetIntroduced: + case Sema::AD_Partial: diag = diag::warn_partial_availability; diag_message = diag::warn_partial_message; diag_fwdclass_message = diag::warn_partial_fwdclass_message; property_note_select = /* partial */ 2; available_here_select_kind = /* partial */ 3; break; - - case AR_Available: - llvm_unreachable("Warning for availability of available declaration?"); - } - - CharSourceRange UseRange; - StringRef Replacement; - if (K == AR_Deprecated) { - if (auto attr = D->getAttr<DeprecatedAttr>()) - Replacement = attr->getReplacement(); - if (auto attr = getAttrForPlatform(S.Context, D)) - Replacement = attr->getReplacement(); - - if (!Replacement.empty()) - UseRange = - CharSourceRange::getCharRange(Loc, S.getLocForEndOfToken(Loc)); } if (!Message.empty()) { - S.Diag(Loc, diag_message) << D << Message - << (UseRange.isValid() ? - FixItHint::CreateReplacement(UseRange, Replacement) : FixItHint()); + S.Diag(Loc, diag_message) << D << Message; if (ObjCProperty) S.Diag(ObjCProperty->getLocation(), diag::note_property_attribute) << ObjCProperty->getDeclName() << property_note_select; } else if (!UnknownObjCClass) { - S.Diag(Loc, diag) << D - << (UseRange.isValid() ? - FixItHint::CreateReplacement(UseRange, Replacement) : FixItHint()); + S.Diag(Loc, diag) << D; if (ObjCProperty) S.Diag(ObjCProperty->getLocation(), diag::note_property_attribute) << ObjCProperty->getDeclName() << property_note_select; } else { - S.Diag(Loc, diag_fwdclass_message) << D - << (UseRange.isValid() ? - FixItHint::CreateReplacement(UseRange, Replacement) : FixItHint()); + S.Diag(Loc, diag_fwdclass_message) << D; S.Diag(UnknownObjCClass->getLocation(), diag::note_forward_class); } - // The declaration can have multiple availability attributes, we are looking - // at one of them. - const AvailabilityAttr *A = getAttrForPlatform(S.Context, D); - if (A && A->isInherited()) { - for (const Decl *Redecl = D->getMostRecentDecl(); Redecl; - Redecl = Redecl->getPreviousDecl()) { - const AvailabilityAttr *AForRedecl = getAttrForPlatform(S.Context, - Redecl); - if (AForRedecl && !AForRedecl->isInherited()) { - // If D is a declaration with inherited attributes, the note should - // point to the declaration with actual attributes. - S.Diag(Redecl->getLocation(), diag_available_here) << D - << available_here_select_kind; - break; - } - } - } - else - S.Diag(D->getLocation(), diag_available_here) - << D << available_here_select_kind; - - if (K == AR_NotYetIntroduced) + S.Diag(D->getLocation(), diag_available_here) + << D << available_here_select_kind; + if (K == Sema::AD_Partial) S.Diag(Loc, diag::note_partial_availability_silence) << D; } static void handleDelayedAvailabilityCheck(Sema &S, DelayedDiagnostic &DD, Decl *Ctx) { - assert(DD.Kind == DelayedDiagnostic::Availability && - "Expected an availability diagnostic here"); - + assert(DD.Kind == DelayedDiagnostic::Deprecation || + DD.Kind == DelayedDiagnostic::Unavailable); + Sema::AvailabilityDiagnostic AD = DD.Kind == DelayedDiagnostic::Deprecation + ? Sema::AD_Deprecation + : Sema::AD_Unavailable; DD.Triggered = true; DoEmitAvailabilityWarning( - S, DD.getAvailabilityResult(), Ctx, DD.getAvailabilityDecl(), - DD.getAvailabilityMessage(), DD.Loc, DD.getUnknownObjCClass(), - DD.getObjCProperty(), false); + S, AD, Ctx, DD.getDeprecationDecl(), DD.getDeprecationMessage(), DD.Loc, + DD.getUnknownObjCClass(), DD.getObjCProperty(), false); } void Sema::PopParsingDeclaration(ParsingDeclState state, Decl *decl) { @@ -6797,7 +5923,8 @@ void Sema::PopParsingDeclaration(ParsingDeclState state, Decl *decl) { continue; switch (diag.Kind) { - case DelayedDiagnostic::Availability: + case DelayedDiagnostic::Deprecation: + case DelayedDiagnostic::Unavailable: // Don't bother giving deprecation/unavailable diagnostics if // the decl is invalid. if (!decl->isInvalidDecl()) @@ -6825,173 +5952,21 @@ void Sema::redelayDiagnostics(DelayedDiagnosticPool &pool) { curPool->steal(pool); } -void Sema::EmitAvailabilityWarning(AvailabilityResult AR, +void Sema::EmitAvailabilityWarning(AvailabilityDiagnostic AD, NamedDecl *D, StringRef Message, SourceLocation Loc, const ObjCInterfaceDecl *UnknownObjCClass, const ObjCPropertyDecl *ObjCProperty, bool ObjCPropertyAccess) { // Delay if we're currently parsing a declaration. - if (DelayedDiagnostics.shouldDelayDiagnostics()) { + if (DelayedDiagnostics.shouldDelayDiagnostics() && AD != AD_Partial) { DelayedDiagnostics.add(DelayedDiagnostic::makeAvailability( - AR, Loc, D, UnknownObjCClass, ObjCProperty, Message, + AD, Loc, D, UnknownObjCClass, ObjCProperty, Message, ObjCPropertyAccess)); return; } Decl *Ctx = cast<Decl>(getCurLexicalContext()); - DoEmitAvailabilityWarning(*this, AR, Ctx, D, Message, Loc, UnknownObjCClass, + DoEmitAvailabilityWarning(*this, AD, Ctx, D, Message, Loc, UnknownObjCClass, ObjCProperty, ObjCPropertyAccess); } - -namespace { - -/// \brief This class implements -Wunguarded-availability. -/// -/// This is done with a traversal of the AST of a function that makes reference -/// to a partially available declaration. Whenever we encounter an \c if of the -/// form: \c if(@available(...)), we use the version from the condition to visit -/// the then statement. -class DiagnoseUnguardedAvailability - : public RecursiveASTVisitor<DiagnoseUnguardedAvailability> { - typedef RecursiveASTVisitor<DiagnoseUnguardedAvailability> Base; - - Sema &SemaRef; - Decl *Ctx; - - /// Stack of potentially nested 'if (@available(...))'s. - SmallVector<VersionTuple, 8> AvailabilityStack; - - void DiagnoseDeclAvailability(NamedDecl *D, SourceRange Range); - -public: - DiagnoseUnguardedAvailability(Sema &SemaRef, Decl *Ctx) - : SemaRef(SemaRef), Ctx(Ctx) { - AvailabilityStack.push_back( - SemaRef.Context.getTargetInfo().getPlatformMinVersion()); - } - - void IssueDiagnostics(Stmt *S) { TraverseStmt(S); } - - bool TraverseIfStmt(IfStmt *If); - - bool VisitObjCMessageExpr(ObjCMessageExpr *Msg) { - if (ObjCMethodDecl *D = Msg->getMethodDecl()) - DiagnoseDeclAvailability( - D, SourceRange(Msg->getSelectorStartLoc(), Msg->getLocEnd())); - return true; - } - - bool VisitDeclRefExpr(DeclRefExpr *DRE) { - DiagnoseDeclAvailability(DRE->getDecl(), - SourceRange(DRE->getLocStart(), DRE->getLocEnd())); - return true; - } - - bool VisitMemberExpr(MemberExpr *ME) { - DiagnoseDeclAvailability(ME->getMemberDecl(), - SourceRange(ME->getLocStart(), ME->getLocEnd())); - return true; - } - - bool VisitTypeLoc(TypeLoc Ty); -}; - -void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability( - NamedDecl *D, SourceRange Range) { - - VersionTuple ContextVersion = AvailabilityStack.back(); - if (AvailabilityResult Result = - SemaRef.ShouldDiagnoseAvailabilityOfDecl(D, nullptr)) { - // All other diagnostic kinds have already been handled in - // DiagnoseAvailabilityOfDecl. - if (Result != AR_NotYetIntroduced) - return; - - const AvailabilityAttr *AA = getAttrForPlatform(SemaRef.getASTContext(), D); - VersionTuple Introduced = AA->getIntroduced(); - - if (ContextVersion >= Introduced) - return; - - // If the context of this function is less available than D, we should not - // emit a diagnostic. - if (!ShouldDiagnoseAvailabilityInContext(SemaRef, Result, Introduced, Ctx)) - return; - - SemaRef.Diag(Range.getBegin(), diag::warn_unguarded_availability) - << Range << D - << AvailabilityAttr::getPrettyPlatformName( - SemaRef.getASTContext().getTargetInfo().getPlatformName()) - << Introduced.getAsString(); - - SemaRef.Diag(D->getLocation(), diag::note_availability_specified_here) - << D << /* partial */ 3; - - // FIXME: Replace this with a fixit diagnostic. - SemaRef.Diag(Range.getBegin(), diag::note_unguarded_available_silence) - << Range << D; - } -} - -bool DiagnoseUnguardedAvailability::VisitTypeLoc(TypeLoc Ty) { - const Type *TyPtr = Ty.getTypePtr(); - SourceRange Range{Ty.getBeginLoc(), Ty.getEndLoc()}; - - if (const TagType *TT = dyn_cast<TagType>(TyPtr)) { - TagDecl *TD = TT->getDecl(); - DiagnoseDeclAvailability(TD, Range); - - } else if (const TypedefType *TD = dyn_cast<TypedefType>(TyPtr)) { - TypedefNameDecl *D = TD->getDecl(); - DiagnoseDeclAvailability(D, Range); - - } else if (const auto *ObjCO = dyn_cast<ObjCObjectType>(TyPtr)) { - if (NamedDecl *D = ObjCO->getInterface()) - DiagnoseDeclAvailability(D, Range); - } - - return true; -} - -bool DiagnoseUnguardedAvailability::TraverseIfStmt(IfStmt *If) { - VersionTuple CondVersion; - if (auto *E = dyn_cast<ObjCAvailabilityCheckExpr>(If->getCond())) { - CondVersion = E->getVersion(); - - // If we're using the '*' case here or if this check is redundant, then we - // use the enclosing version to check both branches. - if (CondVersion.empty() || CondVersion <= AvailabilityStack.back()) - return Base::TraverseStmt(If->getThen()) && - Base::TraverseStmt(If->getElse()); - } else { - // This isn't an availability checking 'if', we can just continue. - return Base::TraverseIfStmt(If); - } - - AvailabilityStack.push_back(CondVersion); - bool ShouldContinue = TraverseStmt(If->getThen()); - AvailabilityStack.pop_back(); - - return ShouldContinue && TraverseStmt(If->getElse()); -} - -} // end anonymous namespace - -void Sema::DiagnoseUnguardedAvailabilityViolations(Decl *D) { - Stmt *Body = nullptr; - - if (auto *FD = D->getAsFunction()) { - // FIXME: We only examine the pattern decl for availability violations now, - // but we should also examine instantiated templates. - if (FD->isTemplateInstantiation()) - return; - - Body = FD->getBody(); - } else if (auto *MD = dyn_cast<ObjCMethodDecl>(D)) - Body = MD->getBody(); - - assert(Body && "Need a body here!"); - - DiagnoseUnguardedAvailability(*this, D).IssueDiagnostics(Body); -} |