Distinguish between attributes explicitly written at the request of the user, and attributes implicitly generated to assist in bookkeeping by the compiler. This is done so by table generating a CreateImplicit method for each attribute.
Additionally, remove the optional nature of the spelling list index when creating attributes. This is supported by table generating a Spelling enumeration when the spellings for an attribute are distinct enough to warrant it. llvm-svn: 199378
This commit is contained in:
parent
c61623b170
commit
36a5350e51
|
@ -48,10 +48,9 @@ protected:
|
|||
/// An index into the spelling list of an
|
||||
/// attribute defined in Attr.td file.
|
||||
unsigned SpellingListIndex : 4;
|
||||
|
||||
bool Inherited : 1;
|
||||
|
||||
bool IsPackExpansion : 1;
|
||||
bool Implicit : 1;
|
||||
|
||||
virtual ~Attr();
|
||||
|
||||
|
@ -76,7 +75,7 @@ public:
|
|||
protected:
|
||||
Attr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex = 0)
|
||||
: Range(R), AttrKind(AK), SpellingListIndex(SpellingListIndex),
|
||||
Inherited(false), IsPackExpansion(false) {}
|
||||
Inherited(false), IsPackExpansion(false), Implicit(false) {}
|
||||
|
||||
public:
|
||||
|
||||
|
@ -93,6 +92,11 @@ public:
|
|||
|
||||
bool isInherited() const { return Inherited; }
|
||||
|
||||
/// \brief Returns true if the attribute has been implicitly created instead
|
||||
/// of explicitly written by the user.
|
||||
bool isImplicit() const { return Implicit; }
|
||||
void setImplicit(bool I) { Implicit = I; }
|
||||
|
||||
void setPackExpansion(bool PE) { IsPackExpansion = PE; }
|
||||
bool isPackExpansion() const { return IsPackExpansion; }
|
||||
|
||||
|
|
|
@ -569,6 +569,7 @@ void ASTDumper::dumpAttr(const Attr *A) {
|
|||
IndentScope Indent(*this);
|
||||
{
|
||||
ColorScope Color(*this, AttrColor);
|
||||
|
||||
switch (A->getKind()) {
|
||||
#define ATTR(X) case attr::X: OS << #X; break;
|
||||
#include "clang/Basic/AttrList.inc"
|
||||
|
@ -579,6 +580,8 @@ void ASTDumper::dumpAttr(const Attr *A) {
|
|||
dumpPointer(A);
|
||||
dumpSourceRange(A->getRange());
|
||||
#include "clang/AST/AttrDump.inc"
|
||||
if (A->isImplicit())
|
||||
OS << " Implicit";
|
||||
}
|
||||
|
||||
static void dumpPreviousDeclImpl(raw_ostream &OS, ...) {}
|
||||
|
|
|
@ -941,7 +941,7 @@ void ObjCMethodDecl::createImplicitParams(ASTContext &Context,
|
|||
setSelfDecl(self);
|
||||
|
||||
if (selfIsConsumed)
|
||||
self->addAttr(new (Context) NSConsumedAttr(SourceLocation(), Context));
|
||||
self->addAttr(NSConsumedAttr::CreateImplicit(Context));
|
||||
|
||||
if (selfIsPseudoStrong)
|
||||
self->setARCPseudoStrong(true);
|
||||
|
|
|
@ -255,7 +255,7 @@ bool Sema::makeUnavailableInSystemHeader(SourceLocation loc,
|
|||
// If the function is already unavailable, it's not an error.
|
||||
if (fn->hasAttr<UnavailableAttr>()) return true;
|
||||
|
||||
fn->addAttr(new (Context) UnavailableAttr(loc, Context, msg));
|
||||
fn->addAttr(UnavailableAttr::CreateImplicit(Context, msg, loc));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -122,10 +122,9 @@ void Sema::AddAlignmentAttributesForRecord(RecordDecl *RD) {
|
|||
// Otherwise, check to see if we need a max field alignment attribute.
|
||||
if (unsigned Alignment = Stack->getAlignment()) {
|
||||
if (Alignment == PackStackEntry::kMac68kAlignmentSentinel)
|
||||
RD->addAttr(::new (Context) AlignMac68kAttr(SourceLocation(), Context));
|
||||
RD->addAttr(AlignMac68kAttr::CreateImplicit(Context));
|
||||
else
|
||||
RD->addAttr(::new (Context) MaxFieldAlignmentAttr(SourceLocation(),
|
||||
Context,
|
||||
RD->addAttr(MaxFieldAlignmentAttr::CreateImplicit(Context,
|
||||
Alignment * 8));
|
||||
}
|
||||
}
|
||||
|
@ -133,7 +132,7 @@ void Sema::AddAlignmentAttributesForRecord(RecordDecl *RD) {
|
|||
void Sema::AddMsStructLayoutForRecord(RecordDecl *RD) {
|
||||
if (!MSStructPragmaOn)
|
||||
return;
|
||||
RD->addAttr(::new (Context) MsStructAttr(SourceLocation(), Context));
|
||||
RD->addAttr(MsStructAttr::CreateImplicit(Context));
|
||||
}
|
||||
|
||||
void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
|
||||
|
@ -312,7 +311,7 @@ void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope,
|
|||
if (VD->isUsed())
|
||||
Diag(PragmaLoc, diag::warn_used_but_marked_unused) << Name;
|
||||
|
||||
VD->addAttr(::new (Context) UnusedAttr(IdTok.getLocation(), Context));
|
||||
VD->addAttr(UnusedAttr::CreateImplicit(Context, IdTok.getLocation()));
|
||||
}
|
||||
|
||||
void Sema::AddCFAuditedAttribute(Decl *D) {
|
||||
|
@ -324,7 +323,7 @@ void Sema::AddCFAuditedAttribute(Decl *D) {
|
|||
D->hasAttr<CFUnknownTransferAttr>())
|
||||
return;
|
||||
|
||||
D->addAttr(::new (Context) CFAuditedTransferAttr(Loc, Context));
|
||||
D->addAttr(CFAuditedTransferAttr::CreateImplicit(Context, Loc));
|
||||
}
|
||||
|
||||
typedef std::vector<std::pair<unsigned, SourceLocation> > VisStack;
|
||||
|
@ -346,7 +345,7 @@ void Sema::AddPushedVisibilityAttribute(Decl *D) {
|
|||
= (VisibilityAttr::VisibilityType) rawType;
|
||||
SourceLocation loc = Stack->back().second;
|
||||
|
||||
D->addAttr(::new (Context) VisibilityAttr(loc, Context, type));
|
||||
D->addAttr(VisibilityAttr::CreateImplicit(Context, type, loc));
|
||||
}
|
||||
|
||||
/// FreeVisContext - Deallocate and null out VisContext.
|
||||
|
|
|
@ -5420,7 +5420,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||
}
|
||||
|
||||
NewVD->addAttr(::new (Context) AsmLabelAttr(SE->getStrTokenLoc(0),
|
||||
Context, Label));
|
||||
Context, Label, 0));
|
||||
} else if (!ExtnameUndeclaredIdentifiers.empty()) {
|
||||
llvm::DenseMap<IdentifierInfo*,AsmLabelAttr*>::iterator I =
|
||||
ExtnameUndeclaredIdentifiers.find(NewVD->getIdentifier());
|
||||
|
@ -6929,7 +6929,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||
// The parser guarantees this is a string.
|
||||
StringLiteral *SE = cast<StringLiteral>(E);
|
||||
NewFD->addAttr(::new (Context) AsmLabelAttr(SE->getStrTokenLoc(0), Context,
|
||||
SE->getString()));
|
||||
SE->getString(), 0));
|
||||
} else if (!ExtnameUndeclaredIdentifiers.empty()) {
|
||||
llvm::DenseMap<IdentifierInfo*,AsmLabelAttr*>::iterator I =
|
||||
ExtnameUndeclaredIdentifiers.find(NewFD->getIdentifier());
|
||||
|
@ -7005,7 +7005,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||
if (D.getDeclSpec().isNoreturnSpecified())
|
||||
NewFD->addAttr(
|
||||
::new(Context) C11NoReturnAttr(D.getDeclSpec().getNoreturnSpecLoc(),
|
||||
Context));
|
||||
Context, 0));
|
||||
|
||||
// Functions returning a variably modified type violate C99 6.7.5.2p2
|
||||
// because all functions have linkage.
|
||||
|
@ -7027,8 +7027,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||
// Attach the attribute to the new decl. Don't apply the attribute if it
|
||||
// returns an instance of the class (e.g. assignment operators).
|
||||
if (!MD || MD->getParent() != Ret) {
|
||||
NewFD->addAttr(new (Context) WarnUnusedResultAttr(SourceRange(),
|
||||
Context));
|
||||
NewFD->addAttr(WarnUnusedResultAttr::CreateImplicit(Context));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7485,8 +7484,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
|
|||
if (OverloadedDecl)
|
||||
Diag(OverloadedDecl->getLocation(),
|
||||
diag::note_attribute_overloadable_prev_overload);
|
||||
NewFD->addAttr(::new (Context) OverloadableAttr(SourceLocation(),
|
||||
Context));
|
||||
NewFD->addAttr(OverloadableAttr::CreateImplicit(Context));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7509,8 +7507,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
|
|||
<< Redeclaration << NewFD;
|
||||
Diag(Previous.getFoundDecl()->getLocation(),
|
||||
diag::note_attribute_overloadable_prev_overload);
|
||||
NewFD->addAttr(::new (Context) OverloadableAttr(SourceLocation(),
|
||||
Context));
|
||||
NewFD->addAttr(OverloadableAttr::CreateImplicit(Context));
|
||||
}
|
||||
if (IsOverload(NewFD, cast<FunctionDecl>(OldDecl), false)) {
|
||||
Redeclaration = false;
|
||||
|
@ -10090,19 +10087,21 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
|
|||
if (FormatIdx < NumParams && // NumParams may be 0 (e.g. vfprintf)
|
||||
FD->getParamDecl(FormatIdx)->getType()->isObjCObjectPointerType())
|
||||
fmt = "NSString";
|
||||
FD->addAttr(::new (Context) FormatAttr(FD->getLocation(), Context,
|
||||
FD->addAttr(FormatAttr::CreateImplicit(Context,
|
||||
&Context.Idents.get(fmt),
|
||||
FormatIdx+1,
|
||||
HasVAListArg ? 0 : FormatIdx+2));
|
||||
HasVAListArg ? 0 : FormatIdx+2,
|
||||
FD->getLocation()));
|
||||
}
|
||||
}
|
||||
if (Context.BuiltinInfo.isScanfLike(BuiltinID, FormatIdx,
|
||||
HasVAListArg)) {
|
||||
if (!FD->hasAttr<FormatAttr>())
|
||||
FD->addAttr(::new (Context) FormatAttr(FD->getLocation(), Context,
|
||||
FD->addAttr(FormatAttr::CreateImplicit(Context,
|
||||
&Context.Idents.get("scanf"),
|
||||
FormatIdx+1,
|
||||
HasVAListArg ? 0 : FormatIdx+2));
|
||||
HasVAListArg ? 0 : FormatIdx+2,
|
||||
FD->getLocation()));
|
||||
}
|
||||
|
||||
// Mark const if we don't care about errno and that is the only
|
||||
|
@ -10111,16 +10110,17 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
|
|||
if (!getLangOpts().MathErrno &&
|
||||
Context.BuiltinInfo.isConstWithoutErrno(BuiltinID)) {
|
||||
if (!FD->hasAttr<ConstAttr>())
|
||||
FD->addAttr(::new (Context) ConstAttr(FD->getLocation(), Context));
|
||||
FD->addAttr(ConstAttr::CreateImplicit(Context, FD->getLocation()));
|
||||
}
|
||||
|
||||
if (Context.BuiltinInfo.isReturnsTwice(BuiltinID) &&
|
||||
!FD->hasAttr<ReturnsTwiceAttr>())
|
||||
FD->addAttr(::new (Context) ReturnsTwiceAttr(FD->getLocation(), Context));
|
||||
FD->addAttr(ReturnsTwiceAttr::CreateImplicit(Context,
|
||||
FD->getLocation()));
|
||||
if (Context.BuiltinInfo.isNoThrow(BuiltinID) && !FD->hasAttr<NoThrowAttr>())
|
||||
FD->addAttr(::new (Context) NoThrowAttr(FD->getLocation(), Context));
|
||||
FD->addAttr(NoThrowAttr::CreateImplicit(Context, FD->getLocation()));
|
||||
if (Context.BuiltinInfo.isConst(BuiltinID) && !FD->hasAttr<ConstAttr>())
|
||||
FD->addAttr(::new (Context) ConstAttr(FD->getLocation(), Context));
|
||||
FD->addAttr(ConstAttr::CreateImplicit(Context, FD->getLocation()));
|
||||
}
|
||||
|
||||
IdentifierInfo *Name = FD->getIdentifier();
|
||||
|
@ -10140,16 +10140,18 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
|
|||
// FIXME: asprintf and vasprintf aren't C99 functions. Should they be
|
||||
// target-specific builtins, perhaps?
|
||||
if (!FD->hasAttr<FormatAttr>())
|
||||
FD->addAttr(::new (Context) FormatAttr(FD->getLocation(), Context,
|
||||
FD->addAttr(FormatAttr::CreateImplicit(Context,
|
||||
&Context.Idents.get("printf"), 2,
|
||||
Name->isStr("vasprintf") ? 0 : 3));
|
||||
Name->isStr("vasprintf") ? 0 : 3,
|
||||
FD->getLocation()));
|
||||
}
|
||||
|
||||
if (Name->isStr("__CFStringMakeConstantString")) {
|
||||
// We already have a __builtin___CFStringMakeConstantString,
|
||||
// but builds that use -fno-constant-cfstrings don't go through that.
|
||||
if (!FD->hasAttr<FormatArgAttr>())
|
||||
FD->addAttr(::new (Context) FormatArgAttr(FD->getLocation(), Context, 1));
|
||||
FD->addAttr(FormatArgAttr::CreateImplicit(Context, 1,
|
||||
FD->getLocation()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11697,8 +11699,9 @@ bool Sema::CheckNontrivialField(FieldDecl *FD) {
|
|||
SourceLocation Loc = FD->getLocation();
|
||||
if (getSourceManager().isInSystemHeader(Loc)) {
|
||||
if (!FD->hasAttr<UnavailableAttr>())
|
||||
FD->addAttr(new (Context) UnavailableAttr(Loc, Context,
|
||||
"this system field has retaining ownership"));
|
||||
FD->addAttr(UnavailableAttr::CreateImplicit(Context,
|
||||
"this system field has retaining ownership",
|
||||
Loc));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -12071,8 +12074,9 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
|
|||
SourceLocation loc = FD->getLocation();
|
||||
if (getSourceManager().isInSystemHeader(loc)) {
|
||||
if (!FD->hasAttr<UnavailableAttr>()) {
|
||||
FD->addAttr(new (Context) UnavailableAttr(loc, Context,
|
||||
"this system field has retaining ownership"));
|
||||
FD->addAttr(UnavailableAttr::CreateImplicit(Context,
|
||||
"this system field has retaining ownership",
|
||||
loc));
|
||||
}
|
||||
} else {
|
||||
Diag(FD->getLocation(), diag::err_arc_objc_object_in_tag)
|
||||
|
@ -13046,8 +13050,8 @@ void Sema::ActOnPragmaRedefineExtname(IdentifierInfo* Name,
|
|||
SourceLocation AliasNameLoc) {
|
||||
Decl *PrevDecl = LookupSingleName(TUScope, Name, NameLoc,
|
||||
LookupOrdinaryName);
|
||||
AsmLabelAttr *Attr =
|
||||
::new (Context) AsmLabelAttr(AliasNameLoc, Context, AliasName->getName());
|
||||
AsmLabelAttr *Attr = ::new (Context) AsmLabelAttr(AliasNameLoc, Context,
|
||||
AliasName->getName(), 0);
|
||||
|
||||
if (PrevDecl)
|
||||
PrevDecl->addAttr(Attr);
|
||||
|
@ -13062,7 +13066,7 @@ void Sema::ActOnPragmaWeakID(IdentifierInfo* Name,
|
|||
Decl *PrevDecl = LookupSingleName(TUScope, Name, NameLoc, LookupOrdinaryName);
|
||||
|
||||
if (PrevDecl) {
|
||||
PrevDecl->addAttr(::new (Context) WeakAttr(PragmaLoc, Context));
|
||||
PrevDecl->addAttr(WeakAttr::CreateImplicit(Context, PragmaLoc));
|
||||
} else {
|
||||
(void)WeakUndeclaredIdentifiers.insert(
|
||||
std::pair<IdentifierInfo*,WeakInfo>
|
||||
|
|
|
@ -565,7 +565,8 @@ static void handleGuardedByAttr(Sema &S, Decl *D, const AttributeList &Attr) {
|
|||
if (!checkGuardedByAttrCommon(S, D, Attr, Arg))
|
||||
return;
|
||||
|
||||
D->addAttr(::new (S.Context) GuardedByAttr(Attr.getRange(), S.Context, Arg));
|
||||
D->addAttr(::new (S.Context) GuardedByAttr(Attr.getRange(), S.Context, Arg,
|
||||
Attr.getAttributeSpellingListIndex()));
|
||||
}
|
||||
|
||||
static void handlePtGuardedByAttr(Sema &S, Decl *D,
|
||||
|
@ -578,7 +579,8 @@ static void handlePtGuardedByAttr(Sema &S, Decl *D,
|
|||
return;
|
||||
|
||||
D->addAttr(::new (S.Context) PtGuardedByAttr(Attr.getRange(),
|
||||
S.Context, Arg));
|
||||
S.Context, Arg,
|
||||
Attr.getAttributeSpellingListIndex()));
|
||||
}
|
||||
|
||||
static bool checkAcquireOrderAttrCommon(Sema &S, Decl *D,
|
||||
|
@ -1083,7 +1085,8 @@ static void handleExtVectorTypeAttr(Sema &S, Scope *scope, Decl *D,
|
|||
|
||||
static void handlePackedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
|
||||
if (TagDecl *TD = dyn_cast<TagDecl>(D))
|
||||
TD->addAttr(::new (S.Context) PackedAttr(Attr.getRange(), S.Context));
|
||||
TD->addAttr(::new (S.Context) PackedAttr(Attr.getRange(), S.Context,
|
||||
Attr.getAttributeSpellingListIndex()));
|
||||
else if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) {
|
||||
// If the alignment is less than or equal to 8 bits, the packed attribute
|
||||
// has no effect.
|
||||
|
@ -2054,7 +2057,8 @@ static void handleObjCMethodFamilyAttr(Sema &S, Decl *decl,
|
|||
}
|
||||
|
||||
method->addAttr(new (S.Context) ObjCMethodFamilyAttr(Attr.getRange(),
|
||||
S.Context, F));
|
||||
S.Context, F,
|
||||
Attr.getAttributeSpellingListIndex()));
|
||||
}
|
||||
|
||||
static void handleObjCNSObject(Sema &S, Decl *D, const AttributeList &Attr) {
|
||||
|
@ -2297,7 +2301,8 @@ static void handleVecTypeHint(Sema &S, Decl *D, const AttributeList &Attr) {
|
|||
}
|
||||
|
||||
D->addAttr(::new (S.Context) VecTypeHintAttr(Attr.getLoc(), S.Context,
|
||||
ParmTSI));
|
||||
ParmTSI,
|
||||
Attr.getAttributeSpellingListIndex()));
|
||||
}
|
||||
|
||||
SectionAttr *Sema::mergeSectionAttr(Decl *D, SourceRange Range,
|
||||
|
@ -3787,8 +3792,10 @@ static void handleMSP430InterruptAttr(Sema &S, Decl *D,
|
|||
return;
|
||||
}
|
||||
|
||||
D->addAttr(::new (S.Context) MSP430InterruptAttr(Attr.getLoc(), S.Context, Num));
|
||||
D->addAttr(::new (S.Context) UsedAttr(Attr.getLoc(), S.Context));
|
||||
D->addAttr(::new (S.Context)
|
||||
MSP430InterruptAttr(Attr.getLoc(), S.Context, Num,
|
||||
Attr.getAttributeSpellingListIndex()));
|
||||
D->addAttr(UsedAttr::CreateImplicit(S.Context));
|
||||
}
|
||||
|
||||
static void handleInterruptAttr(Sema &S, Decl *D, const AttributeList &Attr) {
|
||||
|
@ -3819,8 +3826,9 @@ static void handleX86ForceAlignArgPointerAttr(Sema &S, Decl *D,
|
|||
return;
|
||||
}
|
||||
|
||||
D->addAttr(::new (S.Context) X86ForceAlignArgPointerAttr(Attr.getRange(),
|
||||
S.Context));
|
||||
D->addAttr(::new (S.Context)
|
||||
X86ForceAlignArgPointerAttr(Attr.getRange(), S.Context,
|
||||
Attr.getAttributeSpellingListIndex()));
|
||||
}
|
||||
|
||||
DLLImportAttr *Sema::mergeDLLImportAttr(Decl *D, SourceRange Range,
|
||||
|
@ -4423,9 +4431,9 @@ void Sema::DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W) {
|
|||
if (W.getAlias()) { // clone decl, impersonate __attribute(weak,alias(...))
|
||||
IdentifierInfo *NDId = ND->getIdentifier();
|
||||
NamedDecl *NewD = DeclClonePragmaWeak(ND, W.getAlias(), W.getLocation());
|
||||
NewD->addAttr(::new (Context) AliasAttr(W.getLocation(), Context,
|
||||
NDId->getName()));
|
||||
NewD->addAttr(::new (Context) WeakAttr(W.getLocation(), Context));
|
||||
NewD->addAttr(AliasAttr::CreateImplicit(Context, NDId->getName(),
|
||||
W.getLocation()));
|
||||
NewD->addAttr(WeakAttr::CreateImplicit(Context, W.getLocation()));
|
||||
WeakTopLevelDecl.push_back(NewD);
|
||||
// FIXME: "hideous" code from Sema::LazilyCreateBuiltin
|
||||
// to insert Decl at TU scope, sorry.
|
||||
|
@ -4434,7 +4442,7 @@ void Sema::DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W) {
|
|||
PushOnScopeChains(NewD, S);
|
||||
CurContext = SavedContext;
|
||||
} else { // just add weak to existing
|
||||
ND->addAttr(::new (Context) WeakAttr(W.getLocation(), Context));
|
||||
ND->addAttr(WeakAttr::CreateImplicit(Context, W.getLocation()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4503,8 +4511,9 @@ static bool isForbiddenTypeAllowed(Sema &S, Decl *decl) {
|
|||
static void handleDelayedForbiddenType(Sema &S, DelayedDiagnostic &diag,
|
||||
Decl *decl) {
|
||||
if (decl && isForbiddenTypeAllowed(S, decl)) {
|
||||
decl->addAttr(new (S.Context) UnavailableAttr(diag.Loc, S.Context,
|
||||
"this system declaration uses an unsupported type"));
|
||||
decl->addAttr(UnavailableAttr::CreateImplicit(S.Context,
|
||||
"this system declaration uses an unsupported type",
|
||||
diag.Loc));
|
||||
return;
|
||||
}
|
||||
if (S.getLangOpts().ObjCAutoRefCount)
|
||||
|
|
|
@ -1520,7 +1520,7 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases,
|
|||
Invalid = true;
|
||||
}
|
||||
if (RD->hasAttr<WeakAttr>())
|
||||
Class->addAttr(::new (Context) WeakAttr(SourceRange(), Context));
|
||||
Class->addAttr(WeakAttr::CreateImplicit(Context));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2094,7 +2094,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
|
|||
}
|
||||
|
||||
if (VS.isOverrideSpecified())
|
||||
Member->addAttr(new (Context) OverrideAttr(VS.getOverrideLoc(), Context));
|
||||
Member->addAttr(new (Context) OverrideAttr(VS.getOverrideLoc(), Context, 0));
|
||||
if (VS.isFinalSpecified())
|
||||
Member->addAttr(new (Context) FinalAttr(VS.getFinalLoc(), Context,
|
||||
VS.isFinalSpelledSealed()));
|
||||
|
|
|
@ -98,8 +98,9 @@ bool Sema::checkInitMethod(ObjCMethodDecl *method,
|
|||
// If we're in a system header, and this is not a call, just make
|
||||
// the method unusable.
|
||||
if (receiverTypeIfCall.isNull() && getSourceManager().isInSystemHeader(loc)) {
|
||||
method->addAttr(new (Context) UnavailableAttr(loc, Context,
|
||||
"init method returns a type unrelated to its receiver type"));
|
||||
method->addAttr(UnavailableAttr::CreateImplicit(Context,
|
||||
"init method returns a type unrelated to its receiver type",
|
||||
loc));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -230,8 +231,7 @@ bool Sema::CheckARCMethodDecl(ObjCMethodDecl *method) {
|
|||
if (checkInitMethod(method, QualType()))
|
||||
return true;
|
||||
|
||||
method->addAttr(new (Context) NSConsumesSelfAttr(SourceLocation(),
|
||||
Context));
|
||||
method->addAttr(NSConsumesSelfAttr::CreateImplicit(Context));
|
||||
|
||||
// Don't add a second copy of this attribute, but otherwise don't
|
||||
// let it be suppressed.
|
||||
|
@ -250,8 +250,7 @@ bool Sema::CheckARCMethodDecl(ObjCMethodDecl *method) {
|
|||
break;
|
||||
}
|
||||
|
||||
method->addAttr(new (Context) NSReturnsRetainedAttr(SourceLocation(),
|
||||
Context));
|
||||
method->addAttr(NSReturnsRetainedAttr::CreateImplicit(Context));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -3167,8 +3166,8 @@ Decl *Sema::ActOnMethodDeclaration(
|
|||
if (IMD && IMD->hasAttr<ObjCRequiresSuperAttr>() &&
|
||||
!ObjCMethod->hasAttr<ObjCRequiresSuperAttr>()) {
|
||||
// merge the attribute into implementation.
|
||||
ObjCMethod->addAttr(
|
||||
new (Context) ObjCRequiresSuperAttr(ObjCMethod->getLocation(), Context));
|
||||
ObjCMethod->addAttr(ObjCRequiresSuperAttr::CreateImplicit(Context,
|
||||
ObjCMethod->getLocation()));
|
||||
}
|
||||
if (isa<ObjCCategoryImplDecl>(ImpDecl)) {
|
||||
ObjCMethodFamily family = ObjCMethod->getMethodFamily();
|
||||
|
|
|
@ -2058,8 +2058,7 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
|
|||
if (InitialParam1Type == Param1 &&
|
||||
(NumParams == 1 || InitialParam2Type == Param2)) {
|
||||
if (AddMallocAttr && !Func->hasAttr<MallocAttr>())
|
||||
Func->addAttr(::new (Context) MallocAttr(SourceLocation(),
|
||||
Context));
|
||||
Func->addAttr(MallocAttr::CreateImplicit(Context));
|
||||
// Make the function visible to name lookup, even if we found it in
|
||||
// an unimported module. It either is an implicitly-declared global
|
||||
// allocation function, or is suppressing that function.
|
||||
|
@ -2102,7 +2101,7 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
|
|||
Alloc->setImplicit();
|
||||
|
||||
if (AddMallocAttr)
|
||||
Alloc->addAttr(::new (Context) MallocAttr(SourceLocation(), Context));
|
||||
Alloc->addAttr(MallocAttr::CreateImplicit(Context));
|
||||
|
||||
ParmVarDecl *ParamDecls[2];
|
||||
for (unsigned I = 0; I != NumParams; ++I)
|
||||
|
|
|
@ -1930,16 +1930,16 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
|
|||
if (lexicalDC)
|
||||
GetterMethod->setLexicalDeclContext(lexicalDC);
|
||||
if (property->hasAttr<NSReturnsNotRetainedAttr>())
|
||||
GetterMethod->addAttr(
|
||||
::new (Context) NSReturnsNotRetainedAttr(Loc, Context));
|
||||
GetterMethod->addAttr(NSReturnsNotRetainedAttr::CreateImplicit(Context,
|
||||
Loc));
|
||||
|
||||
if (property->hasAttr<ObjCReturnsInnerPointerAttr>())
|
||||
GetterMethod->addAttr(
|
||||
::new (Context) ObjCReturnsInnerPointerAttr(Loc, Context));
|
||||
ObjCReturnsInnerPointerAttr::CreateImplicit(Context, Loc));
|
||||
|
||||
if (const SectionAttr *SA = property->getAttr<SectionAttr>())
|
||||
GetterMethod->addAttr(::new (Context) SectionAttr(Loc,
|
||||
Context, SA->getName()));
|
||||
GetterMethod->addAttr(SectionAttr::CreateImplicit(Context, SA->getName(),
|
||||
Loc));
|
||||
|
||||
if (getLangOpts().ObjCAutoRefCount)
|
||||
CheckARCMethodDecl(GetterMethod);
|
||||
|
@ -1991,8 +1991,8 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
|
|||
if (lexicalDC)
|
||||
SetterMethod->setLexicalDeclContext(lexicalDC);
|
||||
if (const SectionAttr *SA = property->getAttr<SectionAttr>())
|
||||
SetterMethod->addAttr(::new (Context) SectionAttr(Loc,
|
||||
Context, SA->getName()));
|
||||
SetterMethod->addAttr(SectionAttr::CreateImplicit(Context,
|
||||
SA->getName(), Loc));
|
||||
// It's possible for the user to have set a very odd custom
|
||||
// setter selector that causes it to have a method family.
|
||||
if (getLangOpts().ObjCAutoRefCount)
|
||||
|
|
|
@ -40,7 +40,8 @@ static Attr *handleFallThroughAttr(Sema &S, Stmt *St, const AttributeList &A,
|
|||
S.Diag(A.getRange().getBegin(), diag::err_fallthrough_attr_outside_switch);
|
||||
return 0;
|
||||
}
|
||||
return ::new (S.Context) FallThroughAttr(A.getRange(), S.Context);
|
||||
return ::new (S.Context) FallThroughAttr(A.getRange(), S.Context,
|
||||
A.getAttributeSpellingListIndex());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -157,8 +157,10 @@ static void instantiateDependentEnableIfAttr(
|
|||
return;
|
||||
}
|
||||
|
||||
EnableIfAttr *EIA = new (S.getASTContext()) EnableIfAttr(
|
||||
A->getLocation(), S.getASTContext(), Cond, A->getMessage());
|
||||
EnableIfAttr *EIA = new (S.getASTContext())
|
||||
EnableIfAttr(A->getLocation(), S.getASTContext(), Cond,
|
||||
A->getMessage(),
|
||||
A->getSpellingListIndex());
|
||||
New->addAttr(EIA);
|
||||
}
|
||||
|
||||
|
@ -4391,7 +4393,7 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
|
|||
// find an instantiated decl for (T y) when the ParentDC for y is
|
||||
// the translation unit.
|
||||
// e.g. template <class T> void Foo(auto (*p)(T y) -> decltype(y())) {}
|
||||
// float baz(float(*)()) { return 0.0; }
|
||||
// float baz(float(*)()) { return 0.0; }
|
||||
// Foo(baz);
|
||||
// The better fix here is perhaps to ensure that a ParmVarDecl, by the time
|
||||
// it gets here, always has a FunctionOrMethod as its ParentDC??
|
||||
|
|
|
@ -103,3 +103,10 @@ N: __attribute(()) ;
|
|||
// CHECK: LabelStmt {{.*}} 'N'
|
||||
// CHECK-NEXT: NullStmt
|
||||
}
|
||||
|
||||
namespace Test {
|
||||
extern "C" int printf(const char *format, ...);
|
||||
// CHECK: FunctionDecl{{.*}}printf
|
||||
// CHECK-NEXT: ParmVarDecl{{.*}}format{{.*}}'const char *'
|
||||
// CHECK-NEXT: FormatAttr{{.*}}printf 1 2 Implicit
|
||||
}
|
|
@ -14,6 +14,7 @@
|
|||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/ADT/SmallSet.h"
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/TableGen/Error.h"
|
||||
#include "llvm/TableGen/Record.h"
|
||||
#include "llvm/TableGen/StringMatcher.h"
|
||||
|
@ -61,6 +62,17 @@ static StringRef NormalizeAttrName(StringRef AttrName) {
|
|||
return AttrName;
|
||||
}
|
||||
|
||||
// Normalize the name by removing any and all leading and trailing underscores.
|
||||
// This is different from NormalizeAttrName in that it also handles names like
|
||||
// _pascal and __pascal.
|
||||
static StringRef NormalizeNameForSpellingComparison(StringRef Name) {
|
||||
while (Name.startswith("_"))
|
||||
Name = Name.substr(1, Name.size());
|
||||
while (Name.endswith("_"))
|
||||
Name = Name.substr(0, Name.size() - 1);
|
||||
return Name;
|
||||
}
|
||||
|
||||
// Normalize attribute spelling only if the spelling has both leading
|
||||
// and trailing underscores. For example, __ms_struct__ will be
|
||||
// normalized to "ms_struct"; __cdecl will remain intact.
|
||||
|
@ -151,6 +163,10 @@ namespace {
|
|||
|
||||
virtual bool isEnumArg() const { return false; }
|
||||
virtual bool isVariadicEnumArg() const { return false; }
|
||||
|
||||
virtual void writeImplicitCtorArgs(raw_ostream &OS) const {
|
||||
OS << getUpperName();
|
||||
}
|
||||
};
|
||||
|
||||
class SimpleArgument : public Argument {
|
||||
|
@ -394,6 +410,9 @@ namespace {
|
|||
void writeCtorParameters(raw_ostream &OS) const {
|
||||
OS << "bool Is" << getUpperName() << "Expr, void *" << getUpperName();
|
||||
}
|
||||
void writeImplicitCtorArgs(raw_ostream &OS) const {
|
||||
OS << "Is" << getUpperName() << "Expr, " << getUpperName();
|
||||
}
|
||||
void writeDeclarations(raw_ostream &OS) const {
|
||||
OS << "bool is" << getLowerName() << "Expr;\n";
|
||||
OS << "union {\n";
|
||||
|
@ -491,6 +510,9 @@ namespace {
|
|||
OS << getType() << " *" << getUpperName() << ", unsigned "
|
||||
<< getUpperName() << "Size";
|
||||
}
|
||||
void writeImplicitCtorArgs(raw_ostream &OS) const {
|
||||
OS << getUpperName() << ", " << getUpperName() << "Size";
|
||||
}
|
||||
void writeDeclarations(raw_ostream &OS) const {
|
||||
OS << " unsigned " << getLowerName() << "Size;\n";
|
||||
OS << " " << getType() << " *" << getLowerName() << ";";
|
||||
|
@ -1104,6 +1126,20 @@ static void writeAttrAccessorDefinition(Record &R, raw_ostream &OS) {
|
|||
}
|
||||
}
|
||||
|
||||
static bool SpellingNamesAreCommon(const std::vector<Record *>& Spellings) {
|
||||
assert(!Spellings.empty() && "An empty list of spellings was provided");
|
||||
std::string FirstName = NormalizeNameForSpellingComparison(
|
||||
Spellings.front()->getValueAsString("Name"));
|
||||
for (std::vector<Record *>::const_iterator I = llvm::next(Spellings.begin()),
|
||||
E = Spellings.end(); I != E; ++I) {
|
||||
std::string Name = NormalizeNameForSpellingComparison(
|
||||
(*I)->getValueAsString("Name"));
|
||||
if (Name != FirstName)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace clang {
|
||||
|
||||
// Emits the class definitions for attributes.
|
||||
|
@ -1153,7 +1189,58 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
|
|||
|
||||
ae = Args.end();
|
||||
|
||||
OS << "\n public:\n";
|
||||
OS << "\npublic:\n";
|
||||
|
||||
std::vector<Record *> Spellings = R.getValueAsListOfDefs("Spellings");
|
||||
|
||||
// If there are zero or one spellings, all spelling-related functionality
|
||||
// can be elided. If all of the spellings share the same name, the spelling
|
||||
// functionality can also be elided.
|
||||
bool ElideSpelling = (Spellings.size() <= 1) ||
|
||||
SpellingNamesAreCommon(Spellings);
|
||||
|
||||
if (!ElideSpelling) {
|
||||
OS << " enum Spelling {\n";
|
||||
for (std::vector<Record *>::const_iterator I = Spellings.begin(),
|
||||
E = Spellings.end(); I != E; ++I) {
|
||||
if (I != Spellings.begin())
|
||||
OS << ",\n";
|
||||
const Record &S = **I;
|
||||
std::string Variety = S.getValueAsString("Variety");
|
||||
std::string Spelling = S.getValueAsString("Name");
|
||||
std::string Namespace = "";
|
||||
|
||||
if (Variety == "CXX11")
|
||||
Namespace = S.getValueAsString("Namespace");
|
||||
|
||||
OS << " " << Variety << "_";
|
||||
if (!Namespace.empty())
|
||||
OS << Namespace << "_";
|
||||
OS << Spelling;
|
||||
}
|
||||
OS << "\n };\n\n";
|
||||
}
|
||||
|
||||
OS << " static " << R.getName() << "Attr *CreateImplicit(";
|
||||
OS << "ASTContext &Ctx";
|
||||
if (!ElideSpelling)
|
||||
OS << ", Spelling S";
|
||||
for (ai = Args.begin(); ai != ae; ++ai) {
|
||||
OS << ", ";
|
||||
(*ai)->writeCtorParameters(OS);
|
||||
}
|
||||
OS << ", SourceRange Loc = SourceRange()";
|
||||
OS << ") {\n";
|
||||
OS << " " << R.getName() << "Attr *A = new (Ctx) " << R.getName();
|
||||
OS << "Attr(Loc, Ctx, ";
|
||||
for (ai = Args.begin(); ai != ae; ++ai) {
|
||||
(*ai)->writeImplicitCtorArgs(OS);
|
||||
OS << ", ";
|
||||
}
|
||||
OS << (ElideSpelling ? "0" : "S") << ");\n";
|
||||
OS << " A->setImplicit(true);\n";
|
||||
OS << " return A;\n }\n\n";
|
||||
|
||||
OS << " " << R.getName() << "Attr(SourceRange R, ASTContext &Ctx\n";
|
||||
|
||||
bool HasOpt = false;
|
||||
|
@ -1166,7 +1253,7 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
|
|||
}
|
||||
|
||||
OS << " , ";
|
||||
OS << "unsigned SI = 0\n";
|
||||
OS << "unsigned SI\n";
|
||||
|
||||
OS << " )\n";
|
||||
OS << " : " << SuperName << "(attr::" << R.getName() << ", R, SI)\n";
|
||||
|
@ -1198,7 +1285,7 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
|
|||
}
|
||||
|
||||
OS << " , ";
|
||||
OS << "unsigned SI = 0\n";
|
||||
OS << "unsigned SI\n";
|
||||
|
||||
OS << " )\n";
|
||||
OS << " : " << SuperName << "(attr::" << R.getName() << ", R, SI)\n";
|
||||
|
@ -1483,6 +1570,8 @@ void EmitClangAttrPCHRead(RecordKeeper &Records, raw_ostream &OS) {
|
|||
OS << " case attr::" << R.getName() << ": {\n";
|
||||
if (R.isSubClassOf(InhClass))
|
||||
OS << " bool isInherited = Record[Idx++];\n";
|
||||
OS << " bool isImplicit = Record[Idx++];\n";
|
||||
OS << " unsigned Spelling = Record[Idx++];\n";
|
||||
ArgRecords = R.getValueAsListOfDefs("Args");
|
||||
Args.clear();
|
||||
for (ai = ArgRecords.begin(), ae = ArgRecords.end(); ai != ae; ++ai) {
|
||||
|
@ -1495,9 +1584,10 @@ void EmitClangAttrPCHRead(RecordKeeper &Records, raw_ostream &OS) {
|
|||
OS << ", ";
|
||||
(*ri)->writePCHReadArgs(OS);
|
||||
}
|
||||
OS << ");\n";
|
||||
OS << ", Spelling);\n";
|
||||
if (R.isSubClassOf(InhClass))
|
||||
OS << " cast<InheritableAttr>(New)->setInherited(isInherited);\n";
|
||||
OS << " New->setImplicit(isImplicit);\n";
|
||||
OS << " break;\n";
|
||||
OS << " }\n";
|
||||
}
|
||||
|
@ -1527,6 +1617,9 @@ void EmitClangAttrPCHWrite(RecordKeeper &Records, raw_ostream &OS) {
|
|||
<< "Attr>(A);\n";
|
||||
if (R.isSubClassOf(InhClass))
|
||||
OS << " Record.push_back(SA->isInherited());\n";
|
||||
OS << " Record.push_back(A->isImplicit());\n";
|
||||
OS << " Record.push_back(A->getSpellingListIndex());\n";
|
||||
|
||||
for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai)
|
||||
createArgument(**ai, R.getName())->writePCHWrite(OS);
|
||||
OS << " break;\n";
|
||||
|
@ -1806,7 +1899,7 @@ void EmitClangAttrTemplateInstantiate(RecordKeeper &Records, raw_ostream &OS) {
|
|||
OS << ", ";
|
||||
(*ai)->writeTemplateInstantiationArgs(OS);
|
||||
}
|
||||
OS << ");\n }\n";
|
||||
OS << ", A->getSpellingListIndex());\n }\n";
|
||||
}
|
||||
OS << " } // end switch\n"
|
||||
<< " llvm_unreachable(\"Unknown attribute!\");\n"
|
||||
|
|
Loading…
Reference in New Issue