forked from OSchip/llvm-project
Implementing parsing of template-ids as class-names, so that we can
derive from a class template specialization, e.g., class B : public A<int> { }; llvm-svn: 65488
This commit is contained in:
parent
b750d928ce
commit
d54dfb8718
|
@ -968,7 +968,8 @@ private:
|
|||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// C++ 9: classes [class] and C structs/unions.
|
||||
TypeTy *ParseClassName(const CXXScopeSpec *SS = 0);
|
||||
TypeTy *ParseClassName(SourceLocation &EndLocation,
|
||||
const CXXScopeSpec *SS = 0);
|
||||
void ParseClassSpecifier(DeclSpec &DS,
|
||||
TemplateParameterLists *TemplateParams = 0);
|
||||
void ParseCXXMemberSpecification(SourceLocation StartLoc, unsigned TagType,
|
||||
|
|
|
@ -1822,7 +1822,8 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
|
|||
if (Tok.is(tok::identifier)) {
|
||||
// FIXME: Inaccurate.
|
||||
SourceLocation NameLoc = Tok.getLocation();
|
||||
if (TypeTy *Type = ParseClassName()) {
|
||||
SourceLocation EndLoc;
|
||||
if (TypeTy *Type = ParseClassName(EndLoc)) {
|
||||
D.setDestructor(Type, TildeLoc, NameLoc);
|
||||
} else {
|
||||
D.SetIdentifier(0, TildeLoc);
|
||||
|
|
|
@ -216,16 +216,33 @@ Parser::DeclTy *Parser::ParseUsingDeclaration(unsigned Context,
|
|||
/// ParseClassName - Parse a C++ class-name, which names a class. Note
|
||||
/// that we only check that the result names a type; semantic analysis
|
||||
/// will need to verify that the type names a class. The result is
|
||||
/// either a type or NULL, dependending on whether a type name was
|
||||
/// either a type or NULL, depending on whether a type name was
|
||||
/// found.
|
||||
///
|
||||
/// class-name: [C++ 9.1]
|
||||
/// identifier
|
||||
/// template-id [TODO]
|
||||
/// simple-template-id
|
||||
///
|
||||
Parser::TypeTy *Parser::ParseClassName(const CXXScopeSpec *SS) {
|
||||
// Parse the class-name.
|
||||
// FIXME: Alternatively, parse a simple-template-id.
|
||||
Parser::TypeTy *Parser::ParseClassName(SourceLocation &EndLocation,
|
||||
const CXXScopeSpec *SS) {
|
||||
// Check whether we have a template-id that names a type.
|
||||
if (Tok.is(tok::annot_template_id)) {
|
||||
TemplateIdAnnotation *TemplateId
|
||||
= static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
|
||||
if (TemplateId->Kind == TNK_Class_template) {
|
||||
if (AnnotateTemplateIdTokenAsType(SS))
|
||||
return 0;
|
||||
|
||||
assert(Tok.is(tok::annot_typename) && "template-id -> type failed");
|
||||
TypeTy *Type = Tok.getAnnotationValue();
|
||||
EndLocation = Tok.getAnnotationEndLoc();
|
||||
ConsumeToken();
|
||||
return Type;
|
||||
}
|
||||
|
||||
// Fall through to produce an error below.
|
||||
}
|
||||
|
||||
if (Tok.isNot(tok::identifier)) {
|
||||
Diag(Tok, diag::err_expected_class_name);
|
||||
return 0;
|
||||
|
@ -240,8 +257,7 @@ Parser::TypeTy *Parser::ParseClassName(const CXXScopeSpec *SS) {
|
|||
}
|
||||
|
||||
// Consume the identifier.
|
||||
ConsumeToken();
|
||||
|
||||
EndLocation = ConsumeToken();
|
||||
return Type;
|
||||
}
|
||||
|
||||
|
@ -510,12 +526,13 @@ Parser::BaseResult Parser::ParseBaseSpecifier(DeclTy *ClassDecl)
|
|||
SourceLocation BaseLoc = Tok.getLocation();
|
||||
|
||||
// Parse the class-name.
|
||||
TypeTy *BaseType = ParseClassName(&SS);
|
||||
SourceLocation EndLocation;
|
||||
TypeTy *BaseType = ParseClassName(EndLocation, &SS);
|
||||
if (!BaseType)
|
||||
return true;
|
||||
|
||||
// Find the complete source range for the base-specifier.
|
||||
SourceRange Range(StartLoc, BaseLoc);
|
||||
SourceRange Range(StartLoc, EndLocation);
|
||||
|
||||
// Notify semantic analysis that we have parsed a complete
|
||||
// base-specifier.
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
// RUN: clang -fsyntax-only -verify %s
|
||||
namespace N {
|
||||
template<typename T> class A;
|
||||
|
||||
template<> class A<int> { };
|
||||
|
||||
class B : public A<int> { };
|
||||
}
|
||||
|
||||
class C1 : public N::A<int> { };
|
||||
|
||||
class C2 : public N::A<float> { }; // expected-error{{base class has incomplete type}} \
|
||||
// FIXME: expected-note{{forward declaration of 'class A'}}
|
||||
|
||||
struct D1 {
|
||||
operator N::A<int>();
|
||||
};
|
||||
|
||||
namespace N {
|
||||
struct D2 {
|
||||
operator A<int>();
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue