[cfe-commits] r133854 - in /cfe/trunk: include/clang/Sema/DeclSpec.h include/clang/Sema/LocInfoType.h include/clang/Sema/Sema.h lib/Parse/ParseDeclCXX.cpp lib/Sema/DeclSpec.cpp test/SemaCXX/virtuals.cpp

Douglas Gregor dgregor at apple.com
Fri Jun 24 17:56:28 PDT 2011


Author: dgregor
Date: Fri Jun 24 19:56:27 2011
New Revision: 133854

URL: http://llvm.org/viewvc/llvm-project?rev=133854&view=rev
Log:
When deciding how to parse "= something" as part of a member
declaration, determine whether the declaration will end up declaring a
function using semantic criteria (e.g., it will have function type)
rather than purely syntactic criteria (e.g., it has the form of a
function declarator). Fixes <rdar://problem/9670557>.

Added:
    cfe/trunk/include/clang/Sema/LocInfoType.h
Modified:
    cfe/trunk/include/clang/Sema/DeclSpec.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Parse/ParseDeclCXX.cpp
    cfe/trunk/lib/Sema/DeclSpec.cpp
    cfe/trunk/test/SemaCXX/virtuals.cpp

Modified: cfe/trunk/include/clang/Sema/DeclSpec.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/DeclSpec.h?rev=133854&r1=133853&r2=133854&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/DeclSpec.h (original)
+++ cfe/trunk/include/clang/Sema/DeclSpec.h Fri Jun 24 19:56:27 2011
@@ -1697,6 +1697,14 @@
     return const_cast<Declarator*>(this)->getFunctionTypeInfo();
   }
 
+  /// \brief Determine whether the declaration that will be produced from 
+  /// this declaration will be a function.
+  /// 
+  /// A declaration can declare a function even if the declarator itself
+  /// isn't a function declarator, if the type specifier refers to a function
+  /// type. This routine checks for both cases.
+  bool isDeclarationOfFunction() const;
+  
   /// takeAttributes - Takes attributes from the given parsed-attributes
   /// set and add them to this declarator.
   ///

Added: cfe/trunk/include/clang/Sema/LocInfoType.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/LocInfoType.h?rev=133854&view=auto
==============================================================================
--- cfe/trunk/include/clang/Sema/LocInfoType.h (added)
+++ cfe/trunk/include/clang/Sema/LocInfoType.h Fri Jun 24 19:56:27 2011
@@ -0,0 +1,62 @@
+//===--- LocInfoType.h - Parsed Type with Location Information---*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the LocInfoType class, which holds a type and its
+// source-location information.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_SEMA_LOCINFOTYPE_H
+#define LLVM_CLANG_SEMA_LOCINFOTYPE_H
+
+#include "clang/AST/Type.h"
+
+namespace clang {
+
+class TypeSourceInfo;
+
+/// \brief Holds a QualType and a TypeSourceInfo* that came out of a declarator
+/// parsing.
+///
+/// LocInfoType is a "transient" type, only needed for passing to/from Parser
+/// and Sema, when we want to preserve type source info for a parsed type.
+/// It will not participate in the type system semantics in any way.
+class LocInfoType : public Type {
+  enum {
+    // The last number that can fit in Type's TC.
+    // Avoids conflict with an existing Type class.
+    LocInfo = Type::TypeLast + 1
+  };
+
+  TypeSourceInfo *DeclInfo;
+
+  LocInfoType(QualType ty, TypeSourceInfo *TInfo)
+    : Type((TypeClass)LocInfo, ty, ty->isDependentType(), 
+           ty->isVariablyModifiedType(),
+           ty->containsUnexpandedParameterPack()), 
+    DeclInfo(TInfo) {
+      assert(getTypeClass() == (TypeClass)LocInfo && "LocInfo didn't fit in TC?");
+    }
+  friend class Sema;
+
+ public:
+  QualType getType() const { return getCanonicalTypeInternal(); }
+  TypeSourceInfo *getTypeSourceInfo() const { return DeclInfo; }
+
+  void getAsStringInternal(std::string &Str,
+                           const PrintingPolicy &Policy) const;
+
+  static bool classof(const Type *T) {
+    return T->getTypeClass() == (TypeClass)LocInfo;
+  }
+  static bool classof(const LocInfoType *) { return true; }
+};
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_SEMA_LOCINFOTYPE_H

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=133854&r1=133853&r2=133854&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Fri Jun 24 19:56:27 2011
@@ -20,6 +20,7 @@
 #include "clang/Sema/IdentifierResolver.h"
 #include "clang/Sema/ObjCMethodList.h"
 #include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/LocInfoType.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/DeclarationName.h"
 #include "clang/AST/ExternalASTSource.h"
@@ -157,43 +158,6 @@
   class TemplateDeductionInfo;
 }
 
-/// \brief Holds a QualType and a TypeSourceInfo* that came out of a declarator
-/// parsing.
-///
-/// LocInfoType is a "transient" type, only needed for passing to/from Parser
-/// and Sema, when we want to preserve type source info for a parsed type.
-/// It will not participate in the type system semantics in any way.
-class LocInfoType : public Type {
-  enum {
-    // The last number that can fit in Type's TC.
-    // Avoids conflict with an existing Type class.
-    LocInfo = Type::TypeLast + 1
-  };
-
-  TypeSourceInfo *DeclInfo;
-
-  LocInfoType(QualType ty, TypeSourceInfo *TInfo)
-    : Type((TypeClass)LocInfo, ty, ty->isDependentType(), 
-           ty->isVariablyModifiedType(),
-           ty->containsUnexpandedParameterPack()), 
-      DeclInfo(TInfo) {
-    assert(getTypeClass() == (TypeClass)LocInfo && "LocInfo didn't fit in TC?");
-  }
-  friend class Sema;
-
-public:
-  QualType getType() const { return getCanonicalTypeInternal(); }
-  TypeSourceInfo *getTypeSourceInfo() const { return DeclInfo; }
-
-  void getAsStringInternal(std::string &Str,
-                                   const PrintingPolicy &Policy) const;
-
-  static bool classof(const Type *T) {
-    return T->getTypeClass() == (TypeClass)LocInfo;
-  }
-  static bool classof(const LocInfoType *) { return true; }
-};
-
 // FIXME: No way to easily map from TemplateTypeParmTypes to
 // TemplateTypeParmDecls, so we have this horrible PointerUnion.
 typedef std::pair<llvm::PointerUnion<const TemplateTypeParmType*, NamedDecl*>,

Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=133854&r1=133853&r2=133854&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Fri Jun 24 19:56:27 2011
@@ -1822,7 +1822,7 @@
         Diag(Tok, diag::err_bitfield_member_init);
         SkipUntil(tok::comma, true, true);
       } else {
-        HasDeferredInitializer = !DeclaratorInfo.isFunctionDeclarator() &&
+        HasDeferredInitializer = !DeclaratorInfo.isDeclarationOfFunction() &&
           DeclaratorInfo.getDeclSpec().getStorageClassSpec()
             != DeclSpec::SCS_static &&
           DeclaratorInfo.getDeclSpec().getStorageClassSpec()
@@ -1831,7 +1831,7 @@
         if (!HasDeferredInitializer) {
           SourceLocation EqualLoc;
           Init = ParseCXXMemberInitializer(
-            DeclaratorInfo.isFunctionDeclarator(), EqualLoc);
+            DeclaratorInfo.isDeclarationOfFunction(), EqualLoc);
           if (Init.isInvalid())
             SkipUntil(tok::comma, true, true);
         }

Modified: cfe/trunk/lib/Sema/DeclSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/DeclSpec.cpp?rev=133854&r1=133853&r2=133854&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/DeclSpec.cpp (original)
+++ cfe/trunk/lib/Sema/DeclSpec.cpp Fri Jun 24 19:56:27 2011
@@ -13,8 +13,10 @@
 
 #include "clang/Parse/ParseDiagnostic.h" // FIXME: remove this back-dependency!
 #include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/LocInfoType.h"
 #include "clang/Sema/ParsedTemplate.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/Expr.h"
 #include "clang/AST/NestedNameSpecifier.h"
 #include "clang/AST/TypeLoc.h"
 #include "clang/Lex/Preprocessor.h"
@@ -213,6 +215,59 @@
   return I;
 }
 
+bool Declarator::isDeclarationOfFunction() const {
+  if (isFunctionDeclarator())
+    return true;
+  
+  switch (DS.getTypeSpecType()) {
+    case TST_auto:
+    case TST_bool:
+    case TST_char:
+    case TST_char16:
+    case TST_char32:
+    case TST_class:
+    case TST_decimal128:
+    case TST_decimal32:
+    case TST_decimal64:
+    case TST_double:
+    case TST_enum:
+    case TST_error:
+    case TST_float:
+    case TST_int:
+    case TST_struct:
+    case TST_union:
+    case TST_unknown_anytype:
+    case TST_unspecified:
+    case TST_void:
+    case TST_wchar:
+      return false;
+
+    case TST_decltype:
+    case TST_typeofExpr:
+      if (Expr *E = DS.getRepAsExpr())
+        return E->getType()->isFunctionType();
+      return false;
+     
+    case TST_underlyingType:
+    case TST_typename:
+    case TST_typeofType: {
+      QualType QT = DS.getRepAsType().get();
+      if (QT.isNull())
+        return false;
+      
+      if (const LocInfoType *LIT = dyn_cast<LocInfoType>(QT))
+        QT = LIT->getType();
+
+      if (QT.isNull())
+        return false;
+        
+      return QT->isFunctionType();
+    }
+  }
+  
+  return false;
+}
+
 /// getParsedSpecifiers - Return a bitmask of which flavors of specifiers this
 /// declaration specifier includes.
 ///

Modified: cfe/trunk/test/SemaCXX/virtuals.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/virtuals.cpp?rev=133854&r1=133853&r2=133854&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/virtuals.cpp (original)
+++ cfe/trunk/test/SemaCXX/virtuals.cpp Fri Jun 24 19:56:27 2011
@@ -1,8 +1,8 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fcxx-exceptions -verify %s
 
 class A {
   virtual void f();
-  virtual void g() = 0;
+  virtual void g() = 0; // expected-note{{unimplemented pure virtual method 'g' in 'A'}}
 
   void h() = 0; // expected-error {{'h' is not virtual and cannot be declared pure}}
   void i() = 1; // expected-error {{initializer on function does not look like a pure-specifier}}
@@ -19,20 +19,26 @@
 
 class B : public A {
   // Needs to recognize that overridden function is virtual.
-  //void g() = 0;
+  void g() = 0;
 
   // Needs to recognize that function does not override.
-  //void g(int) = 0;
+  void g(int) = 0; // expected-error{{'g' is not virtual and cannot be declared pure}}
 };
 
 // Needs to recognize invalid uses of abstract classes.
-/*
-A fn(A)
+A fn(A) // expected-error{{parameter type 'A' is an abstract class}} \
+        // expected-error{{return type 'A' is an abstract class}}
 {
-  A a;
-  static_cast<A>(0);
+  A a; // expected-error{{variable type 'A' is an abstract class}}
+  (void)static_cast<A>(0);
   try {
-  } catch(A) {
+  } catch(A) { // expected-error{{variable type 'A' is an abstract class}}
   }
 }
-*/
+
+namespace rdar9670557 {
+  typedef int func(int);
+  struct X {
+    virtual func f = 0;
+  };
+}





More information about the cfe-commits mailing list