]> granicus.if.org Git - clang/commitdiff
Add support for out-of-line definitions of conversion functions and member operators
authorDouglas Gregor <dgregor@apple.com>
Fri, 26 Dec 2008 15:00:45 +0000 (15:00 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 26 Dec 2008 15:00:45 +0000 (15:00 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@61442 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Parse/ParseDecl.cpp
lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclCXX.cpp
test/SemaCXX/nested-name-spec.cpp

index e3fd6961bf8fc18b44a494a92195d439ccf99b1f..23c0c61517d2ef93d8058a26a8541f9c049f6156 100644 (file)
@@ -1514,7 +1514,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
 
         // If this identifier is followed by a '<', we may have a template-id.
         DeclTy *Template;
-        if (getLang().CPlusPlus && NextToken().is(tok::less) &&
+        if (NextToken().is(tok::less) &&
             (Template = Actions.isTemplateName(*Tok.getIdentifierInfo(), 
                                                CurScope))) {
           IdentifierInfo *II = Tok.getIdentifierInfo();
@@ -1525,8 +1525,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
         }
         // If this identifier is the name of the current class, it's a
         // constructor name. 
-        else if (getLang().CPlusPlus &&
-                 Actions.isCurrentClassName(*Tok.getIdentifierInfo(), CurScope))
+        else if (Actions.isCurrentClassName(*Tok.getIdentifierInfo(), CurScope))
           D.setConstructor(Actions.isTypeName(*Tok.getIdentifierInfo(),
                                               CurScope),
                            Tok.getLocation());
@@ -1535,9 +1534,21 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
           D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
         ConsumeToken();
         goto PastIdentifier;
-      }
+      } else if (Tok.is(tok::kw_operator)) {
+        SourceLocation OperatorLoc = Tok.getLocation();
 
-      if (Tok.is(tok::tilde)) {
+        // First try the name of an overloaded operator
+        if (OverloadedOperatorKind Op = TryParseOperatorFunctionId()) {
+          D.setOverloadedOperator(Op, OperatorLoc);
+        } else {
+          // This must be a conversion function (C++ [class.conv.fct]).
+          if (TypeTy *ConvType = ParseConversionFunctionId())
+            D.setConversionFunction(ConvType, OperatorLoc);
+          else
+            D.SetIdentifier(0, Tok.getLocation());
+        }
+        goto PastIdentifier;
+      } else if (Tok.is(tok::tilde)) {
         // This should be a C++ destructor.
         SourceLocation TildeLoc = ConsumeToken();
         if (Tok.is(tok::identifier)) {
@@ -1561,22 +1572,6 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
         goto PastIdentifier;
       }
     }
-
-    if (Tok.is(tok::kw_operator)) {
-      SourceLocation OperatorLoc = Tok.getLocation();
-
-      // First try the name of an overloaded operator
-      if (OverloadedOperatorKind Op = TryParseOperatorFunctionId()) {
-        D.setOverloadedOperator(Op, OperatorLoc);
-      } else {
-        // This must be a conversion function (C++ [class.conv.fct]).
-        if (TypeTy *ConvType = ParseConversionFunctionId())
-          D.setConversionFunction(ConvType, OperatorLoc);
-        else
-          D.SetIdentifier(0, Tok.getLocation());
-      }
-      goto PastIdentifier;
-    }
   }
 
   // If we reached this point, we are either in C/ObjC or the token didn't
index bb0dd4d07cf0ca8041a7695c997e822601d6146c..1f6cbc4f32ccfb06b6cea74346691d2852485d81 100644 (file)
@@ -1186,8 +1186,7 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl,
       } else {
         InvalidDecl = InvalidDecl || CheckConversionDeclarator(D, R, SC);
 
-        NewFD = CXXConversionDecl::Create(Context, 
-                                          cast<CXXRecordDecl>(DC),
+        NewFD = CXXConversionDecl::Create(Context, cast<CXXRecordDecl>(DC),
                                           D.getIdentifierLoc(), Name, R,
                                           isInline, isExplicit);
         
index 48373369bcfcd508b36c6c0c50719f964f23e8e5..5ba2850a3f0b6aae7bef02dc991f190cf4cedeb1 100644 (file)
@@ -1230,21 +1230,6 @@ Sema::DeclTy *Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) {
 
   // Make sure we aren't redeclaring the conversion function.
   QualType ConvType = Context.getCanonicalType(Conversion->getConversionType());
-  OverloadedFunctionDecl *Conversions = ClassDecl->getConversionFunctions();
-  for (OverloadedFunctionDecl::function_iterator Func 
-         = Conversions->function_begin();
-       Func != Conversions->function_end(); ++Func) {
-    CXXConversionDecl *OtherConv = cast<CXXConversionDecl>(*Func);
-    if (ConvType == Context.getCanonicalType(OtherConv->getConversionType())) {
-      Diag(Conversion->getLocation(), diag::err_conv_function_redeclared);
-      Diag(OtherConv->getLocation(),
-           OtherConv->isThisDeclarationADefinition()?
-              diag::note_previous_definition
-            : diag::note_previous_declaration);
-      Conversion->setInvalidDecl();
-      return (DeclTy *)Conversion;      
-    }
-  }
 
   // C++ [class.conv.fct]p1:
   //   [...] A conversion function is never used to convert a
@@ -1272,7 +1257,20 @@ Sema::DeclTy *Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) {
       << ClassType << ConvType;
   }
 
-  ClassDecl->addConversionFunction(Context, Conversion);
+  if (Conversion->getPreviousDeclaration()) {
+    OverloadedFunctionDecl *Conversions = ClassDecl->getConversionFunctions();
+    for (OverloadedFunctionDecl::function_iterator 
+           Conv = Conversions->function_begin(),
+           ConvEnd = Conversions->function_end();
+         Conv != ConvEnd; ++Conv) {
+      if (*Conv == Conversion->getPreviousDeclaration()) {
+        *Conv = Conversion;
+        return (DeclTy *)Conversion;
+      }
+    }
+    assert(Conversion->isInvalidDecl() && "Conversion should not get here.");
+  } else 
+    ClassDecl->addConversionFunction(Context, Conversion);
 
   return (DeclTy *)Conversion;
 }
index 74220662474f2450b830d55afd29f54590e0e5e3..b48207345a56481401b8cf1768cd34a6bfe22f88 100644 (file)
@@ -103,3 +103,23 @@ namespace E {
     }
   }
 }
+
+
+class Operators {
+  Operators operator+(const Operators&) const; // expected-note{{member declaration nearly matches}}
+  operator bool();
+};
+
+Operators Operators::operator+(const Operators&) { // expected-error{{out-of-line definition does not match any declaration in 'Operators'}}
+  Operators ops;
+  return ops;
+}
+
+Operators Operators::operator+(const Operators&) const {
+  Operators ops;
+  return ops;
+}
+
+Operators::operator bool() {
+  return true;
+}