]> granicus.if.org Git - clang/commitdiff
Make FunctionDecl::getReturnTypeSourceRange() support non-builtin types
authorAlp Toker <alp@nuanti.com>
Wed, 2 Jul 2014 12:55:58 +0000 (12:55 +0000)
committerAlp Toker <alp@nuanti.com>
Wed, 2 Jul 2014 12:55:58 +0000 (12:55 +0000)
Also document that the function is a "best-effort" facility to extract source
ranges from limited AST type location info.

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

include/clang/AST/Decl.h
lib/AST/Decl.cpp
lib/Sema/SemaDeclAttr.cpp
test/Sema/warn-main-return-type.c

index 0f04c08742f9a79454cc84973556211091c8188d..978c3c85cef4291f1444b0b19280f63b6fa3af2d 100644 (file)
@@ -1896,6 +1896,9 @@ public:
     return getType()->getAs<FunctionType>()->getReturnType();
   }
 
+  /// \brief Attempt to compute an informative source range covering the
+  /// function return type. This may omit qualifiers and other information with
+  /// limited representation in the AST.
   SourceRange getReturnTypeSourceRange() const;
 
   /// \brief Determine the type of an expression that calls this function.
index 702a2e32e3ea311671886f55d2ae3bdc4fad9813..fdf94a8ad5e81263ca59e7c30c9606316b30d09b 100644 (file)
@@ -2691,17 +2691,20 @@ SourceRange FunctionDecl::getReturnTypeSourceRange() const {
   const TypeSourceInfo *TSI = getTypeSourceInfo();
   if (!TSI)
     return SourceRange();
-
-  TypeLoc TL = TSI->getTypeLoc();
-  FunctionTypeLoc FunctionTL = TL.getAs<FunctionTypeLoc>();
-  if (!FunctionTL)
+  FunctionTypeLoc FTL =
+      TSI->getTypeLoc().IgnoreParens().getAs<FunctionTypeLoc>();
+  if (!FTL)
     return SourceRange();
 
-  TypeLoc ResultTL = FunctionTL.getReturnLoc();
-  if (ResultTL.getUnqualifiedLoc().getAs<BuiltinTypeLoc>())
-    return ResultTL.getSourceRange();
+  // Skip self-referential return types.
+  const SourceManager &SM = getASTContext().getSourceManager();
+  SourceRange RTRange = FTL.getReturnLoc().getSourceRange();
+  SourceLocation Boundary = getNameInfo().getLocStart();
+  if (RTRange.isInvalid() || Boundary.isInvalid() ||
+      !SM.isBeforeInTranslationUnit(RTRange.getEnd(), Boundary))
+    return SourceRange();
 
-  return SourceRange();
+  return RTRange;
 }
 
 /// \brief For an inline function definition in C, or for a gnu_inline function
index dcb6530552df563dddb4300e92581c525019ea83..a1d1d0c4a58423aa1528050ec1042b292bc063fd 100644 (file)
@@ -3029,16 +3029,11 @@ static void handleOptimizeNoneAttr(Sema &S, Decl *D,
 static void handleGlobalAttr(Sema &S, Decl *D, const AttributeList &Attr) {
   FunctionDecl *FD = cast<FunctionDecl>(D);
   if (!FD->getReturnType()->isVoidType()) {
-    TypeLoc TL = FD->getTypeSourceInfo()->getTypeLoc().IgnoreParens();
-    if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) {
-      S.Diag(FD->getTypeSpecStartLoc(), diag::err_kern_type_not_void_return)
+    SourceRange RTRange = FD->getReturnTypeSourceRange();
+    S.Diag(FD->getTypeSpecStartLoc(), diag::err_kern_type_not_void_return)
         << FD->getType()
-        << FixItHint::CreateReplacement(FTL.getReturnLoc().getSourceRange(),
-                                        "void");
-    } else {
-      S.Diag(FD->getTypeSpecStartLoc(), diag::err_kern_type_not_void_return)
-        << FD->getType();
-    }
+        << (RTRange.isValid() ? FixItHint::CreateReplacement(RTRange, "void")
+                              : FixItHint());
     return;
   }
 
index c6f3a0c1011ab834770c4917b6e4c9fc77a75196..f8bcbc555fc516a34ae78ae422bb8059b31452c0 100644 (file)
@@ -22,8 +22,8 @@ double main() {
   return 0.0;
 }
 
-// Currently we suggest to replace only 'float' here because we don't store
-// enough source locations.
+// TODO: Store qualifier source locations for return types so
+// we can replace the full type with this fix-it.
 //
 // expected-error@+3 {{conflicting types for 'main}}
 // expected-warning@+2 {{return type of 'main' is not 'int'}}
@@ -35,9 +35,11 @@ const float main() {
 
 typedef void *(*fptr)(int a);
 
-// expected-error@+2 {{conflicting types for 'main}}
-// expected-warning@+1 {{return type of 'main' is not 'int'}}
+// expected-error@+3 {{conflicting types for 'main}}
+// expected-warning@+2 {{return type of 'main' is not 'int'}}
+// expected-note@+1 {{change return type to 'int'}}
 fptr main() {
+// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:1-[[@LINE-1]]:5}:"int"
   return (fptr) 0;
 }