summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/Attr.h10
-rw-r--r--lib/AST/ASTDumper.cpp3
-rw-r--r--lib/AST/DeclObjC.cpp2
-rw-r--r--lib/Sema/Sema.cpp2
-rw-r--r--lib/Sema/SemaAttr.cpp13
-rw-r--r--lib/Sema/SemaDecl.cpp58
-rw-r--r--lib/Sema/SemaDeclAttr.cpp39
-rw-r--r--lib/Sema/SemaDeclCXX.cpp4
-rw-r--r--lib/Sema/SemaDeclObjC.cpp15
-rw-r--r--lib/Sema/SemaExprCXX.cpp5
-rw-r--r--lib/Sema/SemaObjCProperty.cpp14
-rw-r--r--lib/Sema/SemaStmtAttr.cpp3
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp8
-rw-r--r--test/Misc/ast-dump-attr.cpp7
-rw-r--r--utils/TableGen/ClangAttrEmitter.cpp103
15 files changed, 203 insertions, 83 deletions
diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h
index 61130b5dc1..01c32c0269 100644
--- a/include/clang/AST/Attr.h
+++ b/include/clang/AST/Attr.h
@@ -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; }
diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp
index 5a81966c70..1ee114f3dd 100644
--- a/lib/AST/ASTDumper.cpp
+++ b/lib/AST/ASTDumper.cpp
@@ -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, ...) {}
diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp
index f6685de71a..429b235315 100644
--- a/lib/AST/DeclObjC.cpp
+++ b/lib/AST/DeclObjC.cpp
@@ -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);
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index badff7e0dc..9ab3bea274 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -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;
}
diff --git a/lib/Sema/SemaAttr.cpp b/lib/Sema/SemaAttr.cpp
index 8f9ab32517..0214ba456c 100644
--- a/lib/Sema/SemaAttr.cpp
+++ b/lib/Sema/SemaAttr.cpp
@@ -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.
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index e020df127e..76472651e1 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -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>
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 30f2e67e25..49ab6ed1b8 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -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)
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 9647cea407..c774f25241 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -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()));
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index 34d1965fa5..f7f1b4b565 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -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();
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index a29a279e4b..363c7710b4 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -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)
diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp
index b1343301ef..659b732c81 100644
--- a/lib/Sema/SemaObjCProperty.cpp
+++ b/lib/Sema/SemaObjCProperty.cpp
@@ -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)
diff --git a/lib/Sema/SemaStmtAttr.cpp b/lib/Sema/SemaStmtAttr.cpp
index 80d203e3f5..9bb191d52b 100644
--- a/lib/Sema/SemaStmtAttr.cpp
+++ b/lib/Sema/SemaStmtAttr.cpp
@@ -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());
}
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 6995ae712b..2961e08cc8 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -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??
diff --git a/test/Misc/ast-dump-attr.cpp b/test/Misc/ast-dump-attr.cpp
index 3714cdbb06..5b96797d12 100644
--- a/test/Misc/ast-dump-attr.cpp
+++ b/test/Misc/ast-dump-attr.cpp
@@ -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
+} \ No newline at end of file
diff --git a/utils/TableGen/ClangAttrEmitter.cpp b/utils/TableGen/ClangAttrEmitter.cpp
index b3950c2003..47de7da6a5 100644
--- a/utils/TableGen/ClangAttrEmitter.cpp
+++ b/utils/TableGen/ClangAttrEmitter.cpp
@@ -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"