diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-06-25 00:56:27 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-06-25 00:56:27 +0000 |
commit | 555f57e3549fb5cc963a2ce38180c4f3643a6f95 (patch) | |
tree | db0165f2361a840dbb7a5c72f2e2fe9bc8635eee | |
parent | 831fb9622581fc3b777848e6b097a0cb23d124de (diff) |
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>.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@133854 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Sema/DeclSpec.h | 8 | ||||
-rw-r--r-- | include/clang/Sema/LocInfoType.h | 62 | ||||
-rw-r--r-- | include/clang/Sema/Sema.h | 38 | ||||
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/DeclSpec.cpp | 55 | ||||
-rw-r--r-- | test/SemaCXX/virtuals.cpp | 26 |
6 files changed, 144 insertions, 49 deletions
diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h index e0faab9426..526eed659d 100644 --- a/include/clang/Sema/DeclSpec.h +++ b/include/clang/Sema/DeclSpec.h @@ -1697,6 +1697,14 @@ public: 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. /// diff --git a/include/clang/Sema/LocInfoType.h b/include/clang/Sema/LocInfoType.h new file mode 100644 index 0000000000..566591d150 --- /dev/null +++ b/include/clang/Sema/LocInfoType.h @@ -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 diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 1fa80fc63e..d38667253d 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -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 @@ namespace sema { 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*>, diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 36eb011bc0..b123461f1d 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -1822,7 +1822,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, 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 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, if (!HasDeferredInitializer) { SourceLocation EqualLoc; Init = ParseCXXMemberInitializer( - DeclaratorInfo.isFunctionDeclarator(), EqualLoc); + DeclaratorInfo.isDeclarationOfFunction(), EqualLoc); if (Init.isInvalid()) SkipUntil(tok::comma, true, true); } diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp index f1e8b4ef9c..d450a32e77 100644 --- a/lib/Sema/DeclSpec.cpp +++ b/lib/Sema/DeclSpec.cpp @@ -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 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic, 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. /// diff --git a/test/SemaCXX/virtuals.cpp b/test/SemaCXX/virtuals.cpp index 792467e5f8..8fe7a33a1c 100644 --- a/test/SemaCXX/virtuals.cpp +++ b/test/SemaCXX/virtuals.cpp @@ -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 @@ virtual void A::k() { } // expected-error{{'virtual' can only be specified insid 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; + }; +} |