[cfe-commits] r101098 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaDeclCXX.cpp test/SemaCXX/conversion-function.cpp

John McCall rjmccall at apple.com
Mon Apr 12 17:04:31 PDT 2010


Author: rjmccall
Date: Mon Apr 12 19:04:31 2010
New Revision: 101098

URL: http://llvm.org/viewvc/llvm-project?rev=101098&view=rev
Log:
Diagnose declarations of conversion functions with declarators other than '()'.


Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/test/SemaCXX/conversion-function.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=101098&r1=101097&r2=101098&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Apr 12 19:04:31 2010
@@ -2637,6 +2637,8 @@
   "conversion function cannot convert to an array type">;
 def err_conv_function_to_function : Error<
   "conversion function cannot convert to a function type">;
+def err_conv_function_with_complex_decl : Error<
+  "must use a typedef to declare a conversion to %0">;
 def err_conv_function_redeclared : Error<
   "conversion function cannot be redeclared">;
 def warn_conv_to_self_not_used : Warning<

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=101098&r1=101097&r2=101098&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Apr 12 19:04:31 2010
@@ -2828,6 +2828,9 @@
     D.setInvalidType();
     SC = FunctionDecl::None;
   }
+
+  QualType ConvType = GetTypeFromParser(D.getName().ConversionFunctionId);
+
   if (D.getDeclSpec().hasTypeSpecifier() && !D.isInvalidType()) {
     // Conversion functions don't have return types, but the parser will
     // happily parse something like:
@@ -2840,27 +2843,35 @@
     Diag(D.getIdentifierLoc(), diag::err_conv_function_return_type)
       << SourceRange(D.getDeclSpec().getTypeSpecTypeLoc())
       << SourceRange(D.getIdentifierLoc());
+    D.setInvalidType();
   }
 
+  const FunctionProtoType *Proto = R->getAs<FunctionProtoType>();
+
   // Make sure we don't have any parameters.
-  if (R->getAs<FunctionProtoType>()->getNumArgs() > 0) {
+  if (Proto->getNumArgs() > 0) {
     Diag(D.getIdentifierLoc(), diag::err_conv_function_with_params);
 
     // Delete the parameters.
     D.getTypeObject(0).Fun.freeArgs();
     D.setInvalidType();
+  } else if (Proto->isVariadic()) {
+    Diag(D.getIdentifierLoc(), diag::err_conv_function_variadic);
+    D.setInvalidType();
   }
 
-  // Make sure the conversion function isn't variadic.
-  if (R->getAs<FunctionProtoType>()->isVariadic() && !D.isInvalidType()) {
-    Diag(D.getIdentifierLoc(), diag::err_conv_function_variadic);
+  // Diagnose "&operator bool()" and other such nonsense.  This
+  // is actually a gcc extension which we don't support.
+  if (Proto->getResultType() != ConvType) {
+    Diag(D.getIdentifierLoc(), diag::err_conv_function_with_complex_decl)
+      << Proto->getResultType();
     D.setInvalidType();
+    ConvType = Proto->getResultType();
   }
 
   // C++ [class.conv.fct]p4:
   //   The conversion-type-id shall not represent a function type nor
   //   an array type.
-  QualType ConvType = GetTypeFromParser(D.getName().ConversionFunctionId);
   if (ConvType->isArrayType()) {
     Diag(D.getIdentifierLoc(), diag::err_conv_function_to_array);
     ConvType = Context.getPointerType(ConvType);
@@ -2874,14 +2885,15 @@
   // Rebuild the function type "R" without any parameters (in case any
   // of the errors above fired) and with the conversion type as the
   // return type.
-  const FunctionProtoType *Proto = R->getAs<FunctionProtoType>();
-  R = Context.getFunctionType(ConvType, 0, 0, false,
-                              Proto->getTypeQuals(),
-                              Proto->hasExceptionSpec(),
-                              Proto->hasAnyExceptionSpec(),
-                              Proto->getNumExceptions(),
-                              Proto->exception_begin(),
-                              Proto->getExtInfo());
+  if (D.isInvalidType()) {
+    R = Context.getFunctionType(ConvType, 0, 0, false,
+                                Proto->getTypeQuals(),
+                                Proto->hasExceptionSpec(),
+                                Proto->hasAnyExceptionSpec(),
+                                Proto->getNumExceptions(),
+                                Proto->exception_begin(),
+                                Proto->getExtInfo());
+  }
 
   // C++0x explicit conversion operators.
   if (D.getDeclSpec().isExplicitSpecified() && !getLangOptions().CPlusPlus0x)

Modified: cfe/trunk/test/SemaCXX/conversion-function.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/conversion-function.cpp?rev=101098&r1=101097&r2=101098&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/conversion-function.cpp (original)
+++ cfe/trunk/test/SemaCXX/conversion-function.cpp Mon Apr 12 19:04:31 2010
@@ -165,3 +165,14 @@
 
   E2<int&> e2i; // expected-note{{in instantiation}}
 }
+
+namespace crazy_declarators {
+  struct A {
+    (&operator bool())(); // expected-error {{must use a typedef to declare a conversion to 'bool (&)()'}}
+
+    // FIXME: This diagnostic is misleading (the correct spelling
+    // would be 'operator int*'), but it's a corner case of a
+    // rarely-used syntax extension.
+    *operator int();  // expected-error {{must use a typedef to declare a conversion to 'int *'}}
+  };
+}





More information about the cfe-commits mailing list