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
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 52d9f58..90aa9c1 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -467,11 +467,10 @@
}
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 @@
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 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 @@
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 @@
/// 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 @@
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.