isa<ObjCMethodDecl>(S) ||
isa<BlockDecl>(S)}]>;
+// This is a fake Decl node that represents a function definition as well as a
+// function declaration. This can be used for attributes which are allowed to
+// appear on the definition of a function that's been late parsed. It is
+// treated and diagnosed the same as a FunctionDecl.
+def FunctionDefinition : DDecl<Function, 1>;
+
// A single argument to an attribute
class Argument<string name, bit optional> {
string Name = name;
def NoThreadSafetyAnalysis : InheritableAttr {
let Spellings = [GNU<"no_thread_safety_analysis">];
- let Subjects = SubjectList<[Function, FunctionTemplate]>;
+ let Subjects = SubjectList<[FunctionDefinition, FunctionTemplate]>;
}
def GuardedBy : InheritableAttr {
let LateParsed = 1;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
- let Subjects = SubjectList<[Function, FunctionTemplate]>;
+ let Subjects = SubjectList<[FunctionDefinition, FunctionTemplate]>;
}
def SharedLockFunction : InheritableAttr {
let LateParsed = 1;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
- let Subjects = SubjectList<[Function, FunctionTemplate]>;
+ let Subjects = SubjectList<[FunctionDefinition, FunctionTemplate]>;
}
def AssertExclusiveLock : InheritableAttr {
let LateParsed = 1;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
- let Subjects = SubjectList<[Function, FunctionTemplate]>;
+ let Subjects = SubjectList<[FunctionDefinition, FunctionTemplate]>;
}
def AssertSharedLock : InheritableAttr {
let LateParsed = 1;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
- let Subjects = SubjectList<[Function, FunctionTemplate]>;
+ let Subjects = SubjectList<[FunctionDefinition, FunctionTemplate]>;
}
// The first argument is an integer or boolean value specifying the return value
let LateParsed = 1;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
- let Subjects = SubjectList<[Function, FunctionTemplate]>;
+ let Subjects = SubjectList<[FunctionDefinition, FunctionTemplate]>;
}
// The first argument is an integer or boolean value specifying the return value
let LateParsed = 1;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
- let Subjects = SubjectList<[Function, FunctionTemplate]>;
+ let Subjects = SubjectList<[FunctionDefinition, FunctionTemplate]>;
}
def UnlockFunction : InheritableAttr {
let LateParsed = 1;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
- let Subjects = SubjectList<[Function, FunctionTemplate]>;
+ let Subjects = SubjectList<[FunctionDefinition, FunctionTemplate]>;
}
def LockReturned : InheritableAttr {
let LateParsed = 1;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
- let Subjects = SubjectList<[Function, FunctionTemplate]>;
+ let Subjects = SubjectList<[FunctionDefinition, FunctionTemplate]>;
}
def LocksExcluded : InheritableAttr {
let LateParsed = 1;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
- let Subjects = SubjectList<[Function, FunctionTemplate]>;
+ let Subjects = SubjectList<[FunctionDefinition, FunctionTemplate]>;
}
def ExclusiveLocksRequired : InheritableAttr {
let LateParsed = 1;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
- let Subjects = SubjectList<[Function, FunctionTemplate]>;
+ let Subjects = SubjectList<[FunctionDefinition, FunctionTemplate]>;
}
def SharedLocksRequired : InheritableAttr {
let LateParsed = 1;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
- let Subjects = SubjectList<[Function, FunctionTemplate]>;
+ let Subjects = SubjectList<[FunctionDefinition, FunctionTemplate]>;
}
// C/C++ consumed attributes.
ParsedAttributes &attrs,
SourceLocation *endLoc);
- bool IsThreadSafetyAttribute(StringRef AttrName);
-
void ParseTypeTagForDatatypeAttribute(IdentifierInfo &AttrName,
SourceLocation AttrNameLoc,
ParsedAttributes &Attrs,
bool diagnoseAppertainsTo(class Sema &S, const Decl *D) const;
bool diagnoseLangOpts(class Sema &S) const;
bool existsInTarget(llvm::Triple T) const;
+ bool canAppearOnFunctionDefinition() const;
};
/// A factory, from which one makes pools, from which one creates
// Consume the previously pushed token.
ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
- if (OnDefinition && !IsThreadSafetyAttribute(LA.AttrName.getName())) {
- // FIXME: Do not warn on C++11 attributes, once we start supporting
- // them here.
- Diag(Tok, diag::warn_attribute_on_function_definition)
- << &LA.AttrName;
- }
-
ParsedAttributes Attrs(AttrFactory);
SourceLocation endLoc;
Diag(Tok, diag::warn_attribute_no_decl) << LA.AttrName.getName();
}
- for (unsigned i = 0, ni = LA.Decls.size(); i < ni; ++i) {
+ const AttributeList *AL = Attrs.getList();
+ if (OnDefinition && AL && !AL->isCXX11Attribute() &&
+ !AL->canAppearOnFunctionDefinition())
+ Diag(Tok, diag::warn_attribute_on_function_definition)
+ << &LA.AttrName;
+
+ for (unsigned i = 0, ni = LA.Decls.size(); i < ni; ++i)
Actions.ActOnFinishDelayedAttribute(getCurScope(), LA.Decls[i], Attrs);
- }
if (Tok.getLocation() != OrigLoc) {
// Due to a parsing error, we either went over the cached tokens or
}
}
-/// \brief Wrapper around a case statement checking if AttrName is
-/// one of the thread safety attributes
-bool Parser::IsThreadSafetyAttribute(StringRef AttrName) {
- return llvm::StringSwitch<bool>(AttrName)
- .Case("guarded_by", true)
- .Case("guarded_var", true)
- .Case("pt_guarded_by", true)
- .Case("pt_guarded_var", true)
- .Case("lockable", true)
- .Case("scoped_lockable", true)
- .Case("no_thread_safety_analysis", true)
- .Case("acquired_after", true)
- .Case("acquired_before", true)
- .Case("exclusive_lock_function", true)
- .Case("shared_lock_function", true)
- .Case("exclusive_trylock_function", true)
- .Case("shared_trylock_function", true)
- .Case("unlock_function", true)
- .Case("lock_returned", true)
- .Case("locks_excluded", true)
- .Case("exclusive_locks_required", true)
- .Case("shared_locks_required", true)
- .Default(false);
-}
-
void Parser::ParseTypeTagForDatatypeAttribute(IdentifierInfo &AttrName,
SourceLocation AttrNameLoc,
ParsedAttributes &Attrs,
if (Tok.isNot(tok::equal)) {
AttributeList *DtorAttrs = D.getAttributes();
while (DtorAttrs) {
- if (!IsThreadSafetyAttribute(DtorAttrs->getName()->getName()) &&
+ if (!DtorAttrs->canAppearOnFunctionDefinition() &&
!DtorAttrs->isCXX11Attribute()) {
Diag(DtorAttrs->getLoc(), diag::warn_attribute_on_function_definition)
<< DtorAttrs->getName();
unsigned HasCustomParsing : 1;
unsigned IsTargetSpecific : 1;
unsigned IsType : 1;
+ unsigned CanAppearOnFuncDef : 1;
bool (*DiagAppertainsToDecl)(Sema &S, const AttributeList &Attr,
const Decl *);
bool AttributeList::existsInTarget(llvm::Triple T) const {
return getInfo(*this).ExistsInTarget(T);
}
+
+bool AttributeList::canAppearOnFunctionDefinition() const {
+ return getInfo(*this).CanAppearOnFuncDef;
+}
uint32_t V = StringSwitch<uint32_t>(Name)
.Case("Function", Func)
+ .Case("FunctionDefinition", Func)
.Case("Var", Var)
.Case("ObjCMethod", ObjCMethod)
.Case("ParmVar", Param)
std::string B = R->getName();
if (B == "DeclBase")
return "Decl";
+ else if (B == "FunctionDefinition")
+ return "FunctionDecl";
return B + "Decl";
}
static std::string GenerateCustomAppertainsTo(const Record &Subject,
return FnName;
}
+static bool CanAppearOnFuncDef(const Record &Attr) {
+ // Look at the subjects this function appertains to; if a FunctionDefinition
+ // appears in the list, then this attribute can appear on a function
+ // definition.
+ if (Attr.isValueUnset("Subjects"))
+ return false;
+
+ std::vector<Record *> Subjects = Attr.getValueAsDef("Subjects")->
+ getValueAsListOfDefs("Subjects");
+ for (std::vector<Record *>::const_iterator I = Subjects.begin(),
+ E = Subjects.end(); I != E; ++I) {
+ const Record &Subject = **I;
+ if (Subject.getName() == "FunctionDefinition")
+ return true;
+ }
+ return false;
+}
+
/// Emits the parsed attribute helpers
void EmitClangAttrParsedAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
emitSourceFileHeader("Parsed attribute helpers", OS);
SS << ", " << I->second->getValueAsBit("HasCustomParsing");
SS << ", " << I->second->isSubClassOf("TargetSpecificAttr");
SS << ", " << I->second->isSubClassOf("TypeAttr");
+ SS << ", " << CanAppearOnFuncDef(*I->second);
SS << ", " << GenerateAppertainsTo(*I->second, OS);
SS << ", " << GenerateLangOptRequirements(*I->second, OS);
SS << ", " << GenerateTargetRequirements(*I->second, Dupes, OS);