]> granicus.if.org Git - clang/commitdiff
Merge the "regparm" attribute from a previous declaration of a
authorDouglas Gregor <dgregor@apple.com>
Fri, 18 Jun 2010 21:30:25 +0000 (21:30 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 18 Jun 2010 21:30:25 +0000 (21:30 +0000)
function to redeclarations of that function. Fixes PR7025.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@106317 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaDecl.cpp
test/CodeGen/regparm.c
test/Sema/attr-regparm.c
test/SemaCXX/attr-regparm.cpp [new file with mode: 0644]

index e37a0b5e41f72abfe185a8d227e9dace4ed57407..8f9a8f99742e545311cb851494b7884c2e91c1aa 100644 (file)
@@ -914,6 +914,10 @@ def err_cconv_knr : Error<
   "function with no prototype cannot use %0 calling convention">;
 def err_cconv_varargs : Error<
   "variadic function cannot use %0 calling convention">;
+def err_regparm_mismatch : Error<"function declared with with regparm(%0) "
+  "attribute was previously declared %plural{0:without the regparm|1:"
+  "with the regparm(1)|2:with the regparm(2)|3:with the regparm(3)|:with the"
+  "regparm}1 attribute">;
 
 def warn_impcast_vector_scalar : Warning<
   "implicit cast turns vector to scalar: %0 to %1">,
index 9e31a543722250736d7aa9849cda8d6970bcd43b..528cc65abfcbbe15b005432e3e882a4de8baf969 100644 (file)
@@ -1057,13 +1057,27 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
   }
 
   // FIXME: diagnose the other way around?
-  if (OldType->getNoReturnAttr() &&
-      !NewType->getNoReturnAttr()) {
+  if (OldType->getNoReturnAttr() && !NewType->getNoReturnAttr()) {
     NewQType = Context.getNoReturnType(NewQType);
     New->setType(NewQType);
     assert(NewQType.isCanonical());
   }
 
+  // Merge regparm attribute.
+  if (OldType->getRegParmType() != NewType->getRegParmType()) {
+    if (NewType->getRegParmType()) {
+      Diag(New->getLocation(), diag::err_regparm_mismatch)
+        << NewType->getRegParmType()
+        << OldType->getRegParmType();
+      Diag(Old->getLocation(), diag::note_previous_declaration);      
+      return true;
+    }
+    
+    NewQType = Context.getRegParmType(NewQType, OldType->getRegParmType());
+    New->setType(NewQType);
+    assert(NewQType.isCanonical());    
+  }
+  
   if (getLangOptions().CPlusPlus) {
     // (C++98 13.1p2):
     //   Certain function declarations cannot be overloaded:
index b60f8c70d762ddcae068ae5441e1a58a8085de91..ec5cbab16a5b57a55eef38caa5c2adeeeaf02f50 100644 (file)
@@ -14,6 +14,11 @@ FType bar;
 static void FASTCALL
 reduced(char b, double c, foo* d, double e, int f);
 
+// PR7025
+void FASTCALL f1(int i, int j, int k);
+// CHECK: define void @f1(i32 inreg %i, i32 inreg %j, i32 %k)
+void f1(int i, int j, int k) { }
+
 int
 main(void) {
   // CHECK: call void @reduced(i8 signext inreg 0, {{.*}} %struct.anon* inreg null
index 045a41396e3f2ab0501caaf9894528392bba6479..4049e0e8a13fd44f0182baca1a2003000479de73 100644 (file)
@@ -1,7 +1,11 @@
 // RUN: %clang_cc1 -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)}}
+__attribute((regparm(2))) int x0(void);
+__attribute((regparm(1.0))) int x1(void); // expected-error{{'regparm' attribute requires integer constant}}
+__attribute((regparm(-1))) int x2(void); // expected-error{{'regparm' parameter must be between 0 and 3 inclusive}}
+__attribute((regparm(5))) int x3(void); // expected-error{{'regparm' parameter must be between 0 and 3 inclusive}}
+__attribute((regparm(5,3))) int x4(void); // expected-error{{attribute requires 1 argument(s)}}
+
+void __attribute__((regparm(3))) x5(int);
+void x5(int); // expected-note{{previous declaration is here}}
+void __attribute__((regparm(2))) x5(int); // expected-error{{function declared with with regparm(2) attribute was previously declared with the regparm(3) attribute}}
diff --git a/test/SemaCXX/attr-regparm.cpp b/test/SemaCXX/attr-regparm.cpp
new file mode 100644 (file)
index 0000000..b98631a
--- /dev/null
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// PR7025
+struct X0 {
+  void __attribute__((regparm(3))) f0();
+  void __attribute__((regparm(3))) f1();
+  void __attribute__((regparm(3))) f2(); // expected-note{{previous declaration is here}}
+  void f3(); // expected-note{{previous declaration is here}}
+};
+
+void X0::f0() { }
+void __attribute__((regparm(3))) X0::f1() { }
+void __attribute__((regparm(2))) X0::f2() { } // expected-error{{function declared with with regparm(2) attribute was previously declared with the regparm(3) attribute}}
+void __attribute__((regparm(2))) X0::f3() { } // expected-error{{function declared with with regparm(2) attribute was previously declared without the regparm attribute}}