forked from OSchip/llvm-project
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>. llvm-svn: 133854
This commit is contained in:
parent
03bf47c0f0
commit
c15b0cfc1f
|
@ -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.
|
||||
///
|
||||
|
|
|
@ -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
|
|
@ -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*>,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
///
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue