r195960 - Enables support for custom subject lists for attributes. As a testbed, uses the custom subject for the ibaction attribute.
Aaron Ballman
aaron at aaronballman.com
Fri Nov 29 06:57:59 PST 2013
Author: aaronballman
Date: Fri Nov 29 08:57:58 2013
New Revision: 195960
URL: http://llvm.org/viewvc/llvm-project?rev=195960&view=rev
Log:
Enables support for custom subject lists for attributes. As a testbed, uses the custom subject for the ibaction attribute.
Modified:
cfe/trunk/include/clang/Basic/Attr.td
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/include/clang/Sema/AttributeList.h
cfe/trunk/lib/Sema/SemaDeclAttr.cpp
cfe/trunk/test/SemaObjC/ibaction.m
cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp
Modified: cfe/trunk/include/clang/Basic/Attr.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=195960&r1=195959&r2=195960&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Attr.td (original)
+++ cfe/trunk/include/clang/Basic/Attr.td Fri Nov 29 08:57:58 2013
@@ -37,6 +37,9 @@ def NormalVar : SubsetSubject<Var,
def NonBitField : SubsetSubject<Field,
[{!S->isBitField()}]>;
+def ObjCInstanceMethod : SubsetSubject<ObjCMethod,
+ [{S->isInstanceMethod()}]>;
+
// A single argument to an attribute
class Argument<string name, bit optional> {
string Name = name;
@@ -451,7 +454,8 @@ def Hot : InheritableAttr {
def IBAction : InheritableAttr {
let Spellings = [GNU<"ibaction">];
-// let Subjects = [ObjCMethod];
+ let Subjects = SubjectList<[ObjCInstanceMethod], WarnDiag,
+ "ExpectedObjCInstanceMethod">;
}
def IBOutlet : InheritableAttr {
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=195960&r1=195959&r2=195960&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Nov 29 08:57:58 2013
@@ -2036,7 +2036,8 @@ def warn_attribute_wrong_decl_type : War
"variables, functions and tag types|thread-local variables|"
"variables and fields|variables, data members and tag types|"
"types and namespaces|Objective-C interfaces|methods and properties|"
- "struct or union|struct, union or class|types}1">,
+ "struct or union|struct, union or class|types|"
+ "Objective-C instance methods}1">,
InGroup<IgnoredAttributes>;
def err_attribute_wrong_decl_type : Error<
"%0 attribute only applies to %select{functions|unions|"
@@ -2047,7 +2048,8 @@ def err_attribute_wrong_decl_type : Erro
"variables, functions and tag types|thread-local variables|"
"variables and fields|variables, data members and tag types|"
"types and namespaces|Objective-C interfaces|methods and properties|"
- "struct or union|struct, union or class|types}1">;
+ "struct or union|struct, union or class|types|"
+ "Objective-C instance methods}1">;
def warn_type_attribute_wrong_type : Warning<
"'%0' only applies to %select{function|pointer|"
"Objective-C object or block pointer}1 types; type here is %2">,
@@ -2393,9 +2395,6 @@ def err_attribute_not_supported_in_lang
def warn_attribute_iboutlet : Warning<
"%0 attribute can only be applied to instance variables or properties">,
InGroup<IgnoredAttributes>;
-def warn_attribute_ibaction: Warning<
- "ibaction attribute can only be applied to Objective-C instance methods">,
- InGroup<IgnoredAttributes>;
def err_iboutletcollection_type : Error<
"invalid type %0 as argument of iboutletcollection attribute">;
def err_iboutletcollection_builtintype : Error<
Modified: cfe/trunk/include/clang/Sema/AttributeList.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/AttributeList.h?rev=195960&r1=195959&r2=195960&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/AttributeList.h (original)
+++ cfe/trunk/include/clang/Sema/AttributeList.h Fri Nov 29 08:57:58 2013
@@ -858,7 +858,8 @@ enum AttributeDeclKind {
ExpectedMethodOrProperty,
ExpectedStructOrUnion,
ExpectedStructOrUnionOrClass,
- ExpectedType
+ ExpectedType,
+ ExpectedObjCInstanceMethod
};
} // end namespace clang
Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=195960&r1=195959&r2=195960&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Fri Nov 29 08:57:58 2013
@@ -1119,16 +1119,8 @@ static void handlePackedAttr(Sema &S, De
}
static void handleIBAction(Sema &S, Decl *D, const AttributeList &Attr) {
- // The IBAction attributes only apply to instance methods.
- if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
- if (MD->isInstanceMethod()) {
- D->addAttr(::new (S.Context)
- IBActionAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
- return;
- }
-
- S.Diag(Attr.getLoc(), diag::warn_attribute_ibaction) << Attr.getName();
+ D->addAttr(::new (S.Context) IBActionAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
static bool checkIBOutletCommon(Sema &S, Decl *D, const AttributeList &Attr) {
Modified: cfe/trunk/test/SemaObjC/ibaction.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/ibaction.m?rev=195960&r1=195959&r2=195960&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/ibaction.m (original)
+++ cfe/trunk/test/SemaObjC/ibaction.m Fri Nov 29 08:57:58 2013
@@ -4,12 +4,12 @@
{
__attribute__((iboutlet)) id myoutlet;
}
-+ (void) __attribute__((ibaction)) myClassMethod:(id)msg; // expected-warning{{ibaction attribute can only be applied to Objective-C instance methods}}
++ (void) __attribute__((ibaction)) myClassMethod:(id)msg; // expected-warning{{'ibaction' attribute only applies to Objective-C instance methods}}
- (void) __attribute__((ibaction)) myMessage:(id)msg;
@end
@implementation Foo
-+ (void) __attribute__((ibaction)) myClassMethod:(id)msg {} // expected-warning{{ibaction attribute can only be applied to Objective-C instance methods}}
++ (void) __attribute__((ibaction)) myClassMethod:(id)msg {} // expected-warning{{'ibaction' attribute only applies to Objective-C instance methods}}
// Normally attributes should not be attached to method definitions, but
// we allow 'ibaction' to be attached because it can be expanded from
// the IBAction macro.
Modified: cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp?rev=195960&r1=195959&r2=195960&view=diff
==============================================================================
--- cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp (original)
+++ cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp Fri Nov 29 08:57:58 2013
@@ -21,6 +21,7 @@
#include <algorithm>
#include <cctype>
#include <sstream>
+#include <set>
using namespace llvm;
@@ -1729,7 +1730,19 @@ static std::string CalculateDiagnostic(c
std::vector<Record *> Subjects = S.getValueAsListOfDefs("Subjects");
for (std::vector<Record *>::const_iterator I = Subjects.begin(),
E = Subjects.end(); I != E; ++I) {
- uint32_t V = StringSwitch<uint32_t>((*I)->getName())
+ const Record &R = (**I);
+ std::string Name;
+
+ if (R.isSubClassOf("SubsetSubject")) {
+ PrintError(R.getLoc(), "SubsetSubjects should use a custom diagnostic");
+ // As a fallback, look through the SubsetSubject to see what its base
+ // type is, and use that. This needs to be updated if SubsetSubjects
+ // are allowed within other SubsetSubjects.
+ Name = R.getValueAsDef("Base")->getName();
+ } else
+ Name = R.getName();
+
+ uint32_t V = StringSwitch<uint32_t>(Name)
.Case("Function", Func)
.Case("Var", Var)
.Case("ObjCMethod", ObjCMethod)
@@ -1794,6 +1807,35 @@ static std::string CalculateDiagnostic(c
return "";
}
+static std::string GenerateCustomAppertainsTo(const Record &Subject,
+ raw_ostream &OS) {
+ // If this code has already been generated, simply return the previous
+ // instance of it.
+ static std::set<std::string> CustomSubjectSet;
+ std::set<std::string>::iterator I = CustomSubjectSet.find(Subject.getName());
+ if (I != CustomSubjectSet.end())
+ return *I;
+
+ Record *Base = Subject.getValueAsDef("Base");
+
+ // Not currently support custom subjects within custom subjects.
+ if (Base->isSubClassOf("SubsetSubject")) {
+ PrintFatalError(Subject.getLoc(),
+ "SubsetSubjects within SubsetSubjects is not supported");
+ return "";
+ }
+
+ std::string FnName = "is" + Subject.getName();
+ OS << "static bool " << FnName << "(const Decl *D) {\n";
+ OS << " const " << Base->getName() << "Decl *S = cast<" << Base->getName();
+ OS << "Decl>(D);\n";
+ OS << " return " << Subject.getValueAsString("CheckCode") << ";\n";
+ OS << "}\n\n";
+
+ CustomSubjectSet.insert(FnName);
+ return FnName;
+}
+
static std::string GenerateAppertainsTo(const Record &Attr, raw_ostream &OS) {
// If the attribute does not contain a Subjects definition, then use the
// default appertainsTo logic.
@@ -1808,9 +1850,6 @@ static std::string GenerateAppertainsTo(
if (Subjects.empty())
return "DefaultAppertainsTo";
- // If any of the subjects are a SubsetSubject derivative, bail out for now
- // as though it was using custom parsing.
- bool HasSubsetSubject = false;
bool Warn = SubjectObj->getValueAsDef("Diag")->getValueAsBit("Warn");
// Otherwise, generate an appertainsTo check specific to this attribute which
@@ -1823,10 +1862,17 @@ static std::string GenerateAppertainsTo(
SS << " if (";
for (std::vector<Record *>::const_iterator I = Subjects.begin(),
E = Subjects.end(); I != E; ++I) {
- if ((*I)->isSubClassOf("SubsetSubject"))
- HasSubsetSubject = true;
+ // If the subject has custom code associated with it, generate a function
+ // for it. The function cannot be inlined into this check (yet) because it
+ // requires the subject to be of a specific type, and were that information
+ // inlined here, it would not support an attribute with multiple custom
+ // subjects.
+ if ((*I)->isSubClassOf("SubsetSubject")) {
+ SS << "!" << GenerateCustomAppertainsTo(**I, OS) << "(D)";
+ } else {
+ SS << "!isa<" << (*I)->getName() << "Decl>(D)";
+ }
- SS << "!isa<" << (*I)->getName() << "Decl>(D)";
if (I + 1 != E)
SS << " && ";
}
@@ -1842,9 +1888,6 @@ static std::string GenerateAppertainsTo(
SS << " return true;\n";
SS << "}\n\n";
- if (HasSubsetSubject)
- return "DefaultAppertainsTo";
-
OS << SS.str();
return FnName;
}
More information about the cfe-commits
mailing list