summaryrefslogtreecommitdiff
path: root/gnu/llvm/tools/clang
diff options
context:
space:
mode:
authorPascal Stumpf <pascal@cvs.openbsd.org>2016-09-03 22:46:59 +0000
committerPascal Stumpf <pascal@cvs.openbsd.org>2016-09-03 22:46:59 +0000
commit0fc2cd820c1f7bd4b47498f8319783cf0d02d123 (patch)
tree061fac75f5f69f89ab2ff0fbc2b0d8130fb5b41e /gnu/llvm/tools/clang
parent622d415bb6e3673b59ebf4f59e5499c10d22cd95 (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.h1908
-rw-r--r--gnu/llvm/tools/clang/lib/Sema/SemaChecking.cpp3134
-rw-r--r--gnu/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp1513
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);
-}