aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAbramo Bagnara <abramo.bagnara@gmail.com>2010-04-30 13:10:51 +0000
committerAbramo Bagnara <abramo.bagnara@gmail.com>2010-04-30 13:10:51 +0000
commite215f7232dd4aa65ebf2a1ecd07cd95fe1ce3481 (patch)
tree57b9fc35147d28afd5de78f2ac67ac1d65b42e57
parentb1f1b267351be74013f966f4834cde1eddbe0233 (diff)
Add calling convention related attributes to related declaration. Mark attributes invalid on type related checking so to add them to declarations only when everything is ok.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@102710 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Parse/AttributeList.h4
-rw-r--r--lib/Parse/AttributeList.cpp2
-rw-r--r--lib/Sema/SemaDeclAttr.cpp51
-rw-r--r--lib/Sema/SemaType.cpp35
4 files changed, 73 insertions, 19 deletions
diff --git a/include/clang/Parse/AttributeList.h b/include/clang/Parse/AttributeList.h
index 37acab9b01..12512f33c7 100644
--- a/include/clang/Parse/AttributeList.h
+++ b/include/clang/Parse/AttributeList.h
@@ -41,6 +41,7 @@ class AttributeList {
unsigned NumArgs;
AttributeList *Next;
bool DeclspecAttribute, CXX0XAttribute;
+ mutable bool Invalid; /// True if already diagnosed as invalid.
AttributeList(const AttributeList &); // DO NOT IMPLEMENT
void operator=(const AttributeList &); // DO NOT IMPLEMENT
public:
@@ -128,6 +129,9 @@ public:
bool isDeclspecAttribute() const { return DeclspecAttribute; }
bool isCXX0XAttribute() const { return CXX0XAttribute; }
+ bool isInvalid() const { return Invalid; }
+ void setInvalid(bool b = true) const { Invalid = b; }
+
Kind getKind() const { return getKind(getName()); }
static Kind getKind(const IdentifierInfo *Name);
diff --git a/lib/Parse/AttributeList.cpp b/lib/Parse/AttributeList.cpp
index 0ab67107fa..bae2a09a98 100644
--- a/lib/Parse/AttributeList.cpp
+++ b/lib/Parse/AttributeList.cpp
@@ -23,7 +23,7 @@ AttributeList::AttributeList(IdentifierInfo *aName, SourceLocation aLoc,
AttributeList *n, bool declspec, bool cxx0x)
: AttrName(aName), AttrLoc(aLoc), ScopeName(sName), ScopeLoc(sLoc),
ParmName(pName), ParmLoc(pLoc), NumArgs(numArgs), Next(n),
- DeclspecAttribute(declspec), CXX0XAttribute(cxx0x) {
+ DeclspecAttribute(declspec), CXX0XAttribute(cxx0x), Invalid(false) {
if (numArgs == 0)
Args = 0;
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 52d9f58d37..90aa9c1c13 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -467,11 +467,10 @@ static void HandleMallocAttr(Decl *d, const AttributeList &Attr, Sema &S) {
}
static bool HandleCommonNoReturnAttr(Decl *d, const AttributeList &Attr,
- Sema &S, bool EmitDiagnostics) {
+ Sema &S) {
// check the attribute arguments.
if (Attr.getNumArgs() != 0) {
- if (EmitDiagnostics)
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
return false;
}
@@ -479,11 +478,10 @@ static bool HandleCommonNoReturnAttr(Decl *d, const AttributeList &Attr,
ValueDecl *VD = dyn_cast<ValueDecl>(d);
if (VD == 0 || (!VD->getType()->isBlockPointerType()
&& !VD->getType()->isFunctionPointerType())) {
- if (EmitDiagnostics)
- S.Diag(Attr.getLoc(),
- Attr.isCXX0XAttribute() ? diag::err_attribute_wrong_decl_type
- : diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << 0 /*function*/;
+ S.Diag(Attr.getLoc(),
+ Attr.isCXX0XAttribute() ? diag::err_attribute_wrong_decl_type
+ : diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << 0 /*function*/;
return false;
}
}
@@ -492,17 +490,14 @@ static bool HandleCommonNoReturnAttr(Decl *d, const AttributeList &Attr,
}
static void HandleNoReturnAttr(Decl *d, const AttributeList &Attr, Sema &S) {
- /*
- Do check for well-formedness, but do not emit diagnostics:
- it was already emitted by Sema::ProcessFnAttr().
- */
- if (HandleCommonNoReturnAttr(d, Attr, S, /*EmitDiagnostic=*/false))
- d->addAttr(::new (S.Context) NoReturnAttr());
+ /* Diagnostics (if any) was emitted by Sema::ProcessFnAttr(). */
+ assert(Attr.isInvalid() == false);
+ d->addAttr(::new (S.Context) NoReturnAttr());
}
static void HandleAnalyzerNoReturnAttr(Decl *d, const AttributeList &Attr,
Sema &S) {
- if (HandleCommonNoReturnAttr(d, Attr, S, true))
+ if (HandleCommonNoReturnAttr(d, Attr, S))
d->addAttr(::new (S.Context) AnalyzerNoReturnAttr());
}
@@ -1647,6 +1642,27 @@ static void HandleGNUInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) {
d->addAttr(::new (S.Context) GNUInlineAttr());
}
+static void HandleCallConvAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+ // Diagnostic is emitted elsewhere: here we store the (valid) Attr
+ // in the Decl node for syntactic reasoning, e.g., pretty-printing.
+ assert(Attr.isInvalid() == false);
+
+ switch (Attr.getKind()) {
+ case AttributeList::AT_fastcall:
+ d->addAttr(::new (S.Context) FastCallAttr());
+ return;
+ case AttributeList::AT_stdcall:
+ d->addAttr(::new (S.Context) StdCallAttr());
+ return;
+ case AttributeList::AT_cdecl:
+ d->addAttr(::new (S.Context) CDeclAttr());
+ return;
+ default:
+ llvm_unreachable("unexpected attribute kind");
+ return;
+ }
+}
+
static void HandleRegparmAttr(Decl *d, const AttributeList &Attr, Sema &S) {
// check the attribute arguments.
if (Attr.getNumArgs() != 1) {
@@ -1847,6 +1863,9 @@ static bool isKnownDeclSpecAttr(const AttributeList &Attr) {
/// the wrong thing is illegal (C++0x [dcl.attr.grammar]/4).
static void ProcessDeclAttribute(Scope *scope, Decl *D,
const AttributeList &Attr, Sema &S) {
+ if (Attr.isInvalid())
+ return;
+
if (Attr.isDeclspecAttribute() && !isKnownDeclSpecAttr(Attr))
// FIXME: Try to deal with other __declspec attributes!
return;
@@ -1931,7 +1950,7 @@ static void ProcessDeclAttribute(Scope *scope, Decl *D,
case AttributeList::AT_stdcall:
case AttributeList::AT_cdecl:
case AttributeList::AT_fastcall:
- // These are all treated as type attributes.
+ HandleCallConvAttr(D, Attr, S);
break;
default:
// Ask target about the attribute.
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index dc78fd633f..d1a74beb53 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -81,9 +81,12 @@ static void ProcessDelayedFnAttrs(Sema &S, QualType &Type,
DelayedAttributeSet &Attrs) {
for (DelayedAttributeSet::iterator I = Attrs.begin(),
E = Attrs.end(); I != E; ++I)
- if (ProcessFnAttr(S, Type, *I->first))
+ if (ProcessFnAttr(S, Type, *I->first)) {
S.Diag(I->first->getLoc(), diag::warn_function_attribute_wrong_type)
<< I->first->getName() << I->second;
+ // Avoid any further processing of this attribute.
+ I->first->setInvalid();
+ }
Attrs.clear();
}
@@ -92,6 +95,8 @@ static void DiagnoseDelayedFnAttrs(Sema &S, DelayedAttributeSet &Attrs) {
E = Attrs.end(); I != E; ++I) {
S.Diag(I->first->getLoc(), diag::warn_function_attribute_wrong_type)
<< I->first->getName() << I->second;
+ // Avoid any further processing of this attribute.
+ I->first->setInvalid();
}
Attrs.clear();
}
@@ -1687,12 +1692,14 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type,
// for two or more different address spaces."
if (Type.getAddressSpace()) {
S.Diag(Attr.getLoc(), diag::err_attribute_address_multiple_qualifiers);
+ Attr.setInvalid();
return;
}
// Check the attribute arguments.
if (Attr.getNumArgs() != 1) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ Attr.setInvalid();
return;
}
Expr *ASArgExpr = static_cast<Expr *>(Attr.getArg(0));
@@ -1700,6 +1707,7 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type,
if (!ASArgExpr->isIntegerConstantExpr(addrSpace, S.Context)) {
S.Diag(Attr.getLoc(), diag::err_attribute_address_space_not_int)
<< ASArgExpr->getSourceRange();
+ Attr.setInvalid();
return;
}
@@ -1708,6 +1716,7 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type,
if (addrSpace.isNegative()) {
S.Diag(Attr.getLoc(), diag::err_attribute_address_space_negative)
<< ASArgExpr->getSourceRange();
+ Attr.setInvalid();
return;
}
addrSpace.setIsSigned(false);
@@ -1717,6 +1726,7 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type,
if (addrSpace > max) {
S.Diag(Attr.getLoc(), diag::err_attribute_address_space_too_high)
<< Qualifiers::MaxAddressSpace << ASArgExpr->getSourceRange();
+ Attr.setInvalid();
return;
}
@@ -1730,6 +1740,7 @@ static void HandleObjCGCTypeAttribute(QualType &Type,
const AttributeList &Attr, Sema &S) {
if (Type.getObjCGCAttr() != Qualifiers::GCNone) {
S.Diag(Attr.getLoc(), diag::err_attribute_multiple_objc_gc);
+ Attr.setInvalid();
return;
}
@@ -1737,11 +1748,13 @@ static void HandleObjCGCTypeAttribute(QualType &Type,
if (!Attr.getParameterName()) {
S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
<< "objc_gc" << 1;
+ Attr.setInvalid();
return;
}
Qualifiers::GC GCAttr;
if (Attr.getNumArgs() != 0) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ Attr.setInvalid();
return;
}
if (Attr.getParameterName()->isStr("weak"))
@@ -1751,6 +1764,7 @@ static void HandleObjCGCTypeAttribute(QualType &Type,
else {
S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
<< "objc_gc" << Attr.getParameterName();
+ Attr.setInvalid();
return;
}
@@ -1764,6 +1778,7 @@ bool ProcessFnAttr(Sema &S, QualType &Type, const AttributeList &Attr) {
// Complain immediately if the arg count is wrong.
if (Attr.getNumArgs() != 0) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ Attr.setInvalid();
return false;
}
@@ -1805,6 +1820,7 @@ bool ProcessFnAttr(Sema &S, QualType &Type, const AttributeList &Attr) {
// Otherwise, a calling convention.
if (Attr.getNumArgs() != 0) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ Attr.setInvalid();
return false;
}
@@ -1827,13 +1843,17 @@ bool ProcessFnAttr(Sema &S, QualType &Type, const AttributeList &Attr) {
CallingConv CCOld = Fn->getCallConv();
if (S.Context.getCanonicalCallConv(CC) ==
- S.Context.getCanonicalCallConv(CCOld)) return false;
+ S.Context.getCanonicalCallConv(CCOld)) {
+ Attr.setInvalid();
+ return false;
+ }
if (CCOld != CC_Default) {
// Should we diagnose reapplications of the same convention?
S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
<< FunctionType::getNameForCallConv(CC)
<< FunctionType::getNameForCallConv(CCOld);
+ Attr.setInvalid();
return false;
}
@@ -1842,6 +1862,7 @@ bool ProcessFnAttr(Sema &S, QualType &Type, const AttributeList &Attr) {
if (isa<FunctionNoProtoType>(Fn)) {
S.Diag(Attr.getLoc(), diag::err_cconv_knr)
<< FunctionType::getNameForCallConv(CC);
+ Attr.setInvalid();
return false;
}
@@ -1849,6 +1870,7 @@ bool ProcessFnAttr(Sema &S, QualType &Type, const AttributeList &Attr) {
if (FnP->isVariadic()) {
S.Diag(Attr.getLoc(), diag::err_cconv_varargs)
<< FunctionType::getNameForCallConv(CC);
+ Attr.setInvalid();
return false;
}
}
@@ -1868,6 +1890,7 @@ static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr, S
// Check the attribute arugments.
if (Attr.getNumArgs() != 1) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ Attr.setInvalid();
return;
}
Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0));
@@ -1875,12 +1898,14 @@ static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr, S
if (!sizeExpr->isIntegerConstantExpr(vecSize, S.Context)) {
S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
<< "vector_size" << sizeExpr->getSourceRange();
+ Attr.setInvalid();
return;
}
// the base type must be integer or float, and can't already be a vector.
if (CurType->isVectorType() ||
(!CurType->isIntegerType() && !CurType->isRealFloatingType())) {
S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << CurType;
+ Attr.setInvalid();
return;
}
unsigned typeSize = static_cast<unsigned>(S.Context.getTypeSize(CurType));
@@ -1891,11 +1916,13 @@ static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr, S
if (vectorSize % typeSize) {
S.Diag(Attr.getLoc(), diag::err_attribute_invalid_size)
<< sizeExpr->getSourceRange();
+ Attr.setInvalid();
return;
}
if (vectorSize == 0) {
S.Diag(Attr.getLoc(), diag::err_attribute_zero_size)
<< sizeExpr->getSourceRange();
+ Attr.setInvalid();
return;
}
@@ -1912,6 +1939,10 @@ void ProcessTypeAttributeList(Sema &S, QualType &Result,
// type, but others can be present in the type specifiers even though they
// apply to the decl. Here we apply type attributes and ignore the rest.
for (; AL; AL = AL->getNext()) {
+ // Skip attributes that were marked to be invalid.
+ if (AL->isInvalid())
+ continue;
+
// If this is an attribute we can handle, do so now,
// otherwise, add it to the FnAttrs list for rechaining.
switch (AL->getKind()) {