]> granicus.if.org Git - clang/commitdiff
Improve diagnostics and template instantiation behavior when calling
authorDouglas Gregor <dgregor@apple.com>
Wed, 21 Oct 2009 06:18:39 +0000 (06:18 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 21 Oct 2009 06:18:39 +0000 (06:18 +0000)
an overloaded function call operator.

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

include/clang/Basic/Diagnostic.h
include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaOverload.cpp
test/SemaCXX/incomplete-call.cpp

index 3b450f5d07904089d34641bb6762b3193b1d3e2d..005aab3fa6a12541c166a66590ed173bbd3f39aa 100644 (file)
@@ -44,7 +44,7 @@ namespace clang {
       DIAG_START_PARSE    = DIAG_START_LEX      +  300,
       DIAG_START_AST      = DIAG_START_PARSE    +  300,
       DIAG_START_SEMA     = DIAG_START_AST      +  100,
-      DIAG_START_ANALYSIS = DIAG_START_SEMA     + 1000,
+      DIAG_START_ANALYSIS = DIAG_START_SEMA     + 1100,
       DIAG_UPPER_LIMIT    = DIAG_START_ANALYSIS +  100
     };
 
index bf2acfc06b9bde0fdc22eae4b0cf6ee9867a9ded..d92bb9cdc9b33eb958213d0698d66a7727855cf9 100644 (file)
@@ -1746,7 +1746,9 @@ def err_not_tag_in_scope : Error<
 
 def err_cannot_form_pointer_to_member_of_reference_type : Error<
   "cannot form a pointer-to-member to member %0 of reference type %1">;
-
+def err_incomplete_object_call : Error<
+  "incomplete type in call to object of type %0">;
+  
 def warn_condition_is_assignment : Warning<"using the result of an "
   "assignment as a condition without parentheses">,
   InGroup<Parentheses>;
index 5b40aacc29c5c41ce3161be91084529ca757b62a..5c3e131eb4f370ff4d82bc1674e327704d51b065 100644 (file)
@@ -5086,6 +5086,11 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
     AddMethodCandidate(cast<CXXMethodDecl>(*Oper), Object, Args, NumArgs,
                        CandidateSet, /*SuppressUserConversions=*/false);
 
+  if (RequireCompleteType(LParenLoc, Object->getType(), 
+                          PartialDiagnostic(diag::err_incomplete_object_call)
+                            << Object->getSourceRange()))
+    return true;
+  
   // C++ [over.call.object]p2:
   //   In addition, for each conversion function declared in T of the
   //   form
@@ -5103,33 +5108,30 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
   //   functions for each conversion function declared in an
   //   accessible base class provided the function is not hidden
   //   within T by another intervening declaration.
+  // FIXME: Look in base classes for more conversion operators!
+  OverloadedFunctionDecl *Conversions
+    = cast<CXXRecordDecl>(Record->getDecl())->getConversionFunctions();
+  for (OverloadedFunctionDecl::function_iterator
+         Func = Conversions->function_begin(),
+         FuncEnd = Conversions->function_end();
+       Func != FuncEnd; ++Func) {
+    CXXConversionDecl *Conv;
+    FunctionTemplateDecl *ConvTemplate;
+    GetFunctionAndTemplate(*Func, Conv, ConvTemplate);
 
-  if (!RequireCompleteType(SourceLocation(), Object->getType(), 0)) {
-    // FIXME: Look in base classes for more conversion operators!
-    OverloadedFunctionDecl *Conversions
-      = cast<CXXRecordDecl>(Record->getDecl())->getConversionFunctions();
-    for (OverloadedFunctionDecl::function_iterator
-           Func = Conversions->function_begin(),
-           FuncEnd = Conversions->function_end();
-         Func != FuncEnd; ++Func) {
-      CXXConversionDecl *Conv;
-      FunctionTemplateDecl *ConvTemplate;
-      GetFunctionAndTemplate(*Func, Conv, ConvTemplate);
-
-      // Skip over templated conversion functions; they aren't
-      // surrogates.
-      if (ConvTemplate)
-        continue;
+    // Skip over templated conversion functions; they aren't
+    // surrogates.
+    if (ConvTemplate)
+      continue;
 
-      // Strip the reference type (if any) and then the pointer type (if
-      // any) to get down to what might be a function type.
-      QualType ConvType = Conv->getConversionType().getNonReferenceType();
-      if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>())
-        ConvType = ConvPtrType->getPointeeType();
+    // Strip the reference type (if any) and then the pointer type (if
+    // any) to get down to what might be a function type.
+    QualType ConvType = Conv->getConversionType().getNonReferenceType();
+    if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>())
+      ConvType = ConvPtrType->getPointeeType();
 
-      if (const FunctionProtoType *Proto = ConvType->getAs<FunctionProtoType>())
-        AddSurrogateCandidate(Conv, Proto, Object, Args, NumArgs, CandidateSet);
-    }
+    if (const FunctionProtoType *Proto = ConvType->getAs<FunctionProtoType>())
+      AddSurrogateCandidate(Conv, Proto, Object, Args, NumArgs, CandidateSet);
   }
 
   // Perform overload resolution.
index 08bfdefd6247869091293d123a5caf30d31b5e39..3ce898a76f2ccb87c1c8914e63efa91a717b02fe 100644 (file)
@@ -40,3 +40,10 @@ void g() {
   (b.*mfp)(); // expected-error {{calling function with incomplete return type 'struct A'}}
   
 }
+
+
+struct C; // expected-note{{forward declaration}}
+
+void test_incomplete_object_call(C& c) {
+  c(); // expected-error{{incomplete type in call to object of type}}
+}