From: Eli Friedman Date: Fri, 27 Mar 2009 21:06:47 +0000 (+0000) Subject: Finish off semantic analysis for regparm, and remove the warning. Also X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=55d3aaf9a537888734762170823daf750ea9036d;p=clang Finish off semantic analysis for regparm, and remove the warning. Also remove a redundant error in CodeGen. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@67868 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h index f9081050c5..2a2d0f377b 100644 --- a/include/clang/AST/Attr.h +++ b/include/clang/AST/Attr.h @@ -547,9 +547,13 @@ public: }; class RegparmAttr : public Attr { + unsigned NumParams; + public: - RegparmAttr() : Attr(Regparm) {} - + RegparmAttr(unsigned np) : Attr(Regparm), NumParams(np) {} + + unsigned getNumParams() { return NumParams; } + // Implement isa/cast/dyncast/etc. static bool classof(const Attr *A) { return A->getKind() == Regparm; } diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index c684f4ef52..552bb9a305 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -435,6 +435,10 @@ def err_attribute_cleanup_func_must_take_one_arg : Error< def err_attribute_cleanup_func_arg_incompatible_type : Error< "'cleanup' function %0 parameter has type %1 which is incompatible with " "type %2">; +def err_attribute_regparm_wrong_platform : Error< + "'regparm' is not valid on platforms other than x86-32">; +def err_attribute_regparm_invalid_number : Error< + "'regparm' parameter must be between 0 and 3 inclusive">; // Clang-Specific Attributes diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 0759abdd33..907ade569b 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -311,9 +311,6 @@ void CodeGenModule::SetFunctionAttributesForDefinition(const Decl *D, if (D->getAttr()) F->addFnAttr(llvm::Attribute::NoInline); - - if (D->getAttr()) - ErrorUnsupported(D, "regparm attribute"); } void CodeGenModule::SetMethodAttributes(const ObjCMethodDecl *MD, diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index c8d98cf0dc..40e4971d2b 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -1447,17 +1447,39 @@ static void HandleNoinlineAttr(Decl *d, const AttributeList &Attr, Sema &S) { static void HandleRegparmAttr(Decl *d, const AttributeList &Attr, Sema &S) { // check the attribute arguments. if (Attr.getNumArgs() != 1) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; return; } - + if (!isFunctionOrMethod(d)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << "regparm" << 0 /*function*/; return; } - - d->addAttr(::new (S.Context) RegparmAttr()); + + Expr *NumParamsExpr = static_cast(Attr.getArg(0)); + llvm::APSInt NumParams(32); + if (!NumParamsExpr->isIntegerConstantExpr(NumParams, S.Context)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) + << "regparm" << NumParamsExpr->getSourceRange(); + return; + } + + if (NumParams.getLimitedValue(4) > 3) { + S.Diag(Attr.getLoc(), diag::err_attribute_regparm_invalid_number) + << NumParamsExpr->getSourceRange(); + return; + } + + const char *TargetPrefix = S.Context.Target.getTargetPrefix(); + unsigned PointerWidth = S.Context.Target.getPointerWidth(0); + if (strcmp(TargetPrefix, "x86") || PointerWidth != 32) { + S.Diag(Attr.getLoc(), diag::err_attribute_regparm_wrong_platform) + << NumParamsExpr->getSourceRange(); + return; + } + + d->addAttr(::new (S.Context) RegparmAttr(NumParams.getZExtValue())); } //===----------------------------------------------------------------------===// @@ -1520,10 +1542,7 @@ static void ProcessDeclAttribute(Decl *D, const AttributeList &Attr, Sema &S) { case AttributeList::AT_cleanup: HandleCleanupAttr (D, Attr, S); break; case AttributeList::AT_nodebug: HandleNodebugAttr (D, Attr, S); break; case AttributeList::AT_noinline: HandleNoinlineAttr (D, Attr, S); break; - case AttributeList::AT_regparm: - HandleRegparmAttr (D, Attr, S); - S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); - break; + case AttributeList::AT_regparm: HandleRegparmAttr (D, Attr, S); break; case AttributeList::IgnoredAttribute: // Just ignore break; diff --git a/test/Sema/attr-regparm.c b/test/Sema/attr-regparm.c new file mode 100644 index 0000000000..944f01489c --- /dev/null +++ b/test/Sema/attr-regparm.c @@ -0,0 +1,7 @@ +// RUN: clang-cc -triple i386-apple-darwin9 -fsyntax-only -verify %s + +__attribute((regparm(2))) int x(void); +__attribute((regparm(1.0))) int x(void); // expected-error{{'regparm' attribute requires integer constant}} +__attribute((regparm(-1))) int x(void); // expected-error{{'regparm' parameter must be between 0 and 3 inclusive}} +__attribute((regparm(5))) int x(void); // expected-error{{'regparm' parameter must be between 0 and 3 inclusive}} +__attribute((regparm(5,3))) int x(void); // expected-error{{attribute requires 1 argument(s)}}