[cfe-commits] r130288 - in /cfe/trunk: lib/Parse/ParseStmt.cpp lib/Parse/Parser.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaTemplate.cpp test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp test/FixIt/typo.cpp test/SemaCXX/PR9459.cpp test/SemaTemplate/deduction-crash.cpp
Douglas Gregor
dgregor at apple.com
Tue Apr 26 21:48:22 PDT 2011
Author: dgregor
Date: Tue Apr 26 23:48:22 2011
New Revision: 130288
URL: http://llvm.org/viewvc/llvm-project?rev=130288&view=rev
Log:
Extend Sema::ClassifyName() to support C++, ironing out a few issues
in the classification of template names and using declarations. We now
properly typo-correct the leading identifiers in statements to types,
templates, values, etc. As an added bonus, this reduces the number of
lookups required for disambiguation.
Modified:
cfe/trunk/lib/Parse/ParseStmt.cpp
cfe/trunk/lib/Parse/Parser.cpp
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaTemplate.cpp
cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp
cfe/trunk/test/FixIt/typo.cpp
cfe/trunk/test/SemaCXX/PR9459.cpp
cfe/trunk/test/SemaTemplate/deduction-crash.cpp
Modified: cfe/trunk/lib/Parse/ParseStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseStmt.cpp?rev=130288&r1=130287&r2=130288&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseStmt.cpp (original)
+++ cfe/trunk/lib/Parse/ParseStmt.cpp Tue Apr 26 23:48:22 2011
@@ -113,7 +113,7 @@
return ParseLabeledStatement(attrs);
}
- if (!getLang().CPlusPlus) {
+ if (Next.isNot(tok::coloncolon)) {
// FIXME: Temporarily enable this code only for C.
CXXScopeSpec SS;
IdentifierInfo *Name = Tok.getIdentifierInfo();
@@ -147,7 +147,7 @@
// we're in a syntactic context we haven't handled yet.
break;
- case Sema::NC_Type:
+ case Sema::NC_Type: {
// We have a type. In C, this means that we have a declaration.
if (!getLang().CPlusPlus) {
ParsedType Type = Classification.getType();
@@ -195,9 +195,15 @@
return Actions.ActOnDeclStmt(Decl, DeclStart, DeclEnd);
}
- // In C++, we might also have a functional-style cast.
- // FIXME: Implement this!
+ // In C++, we might also have a functional-style cast. Just annotate
+ // this as a type token.
+ Tok.setKind(tok::annot_typename);
+ setTypeAnnotation(Tok, Classification.getType());
+ Tok.setAnnotationEndLoc(NameLoc);
+ Tok.setLocation(NameLoc);
+ PP.AnnotateCachedTokens(Tok);
break;
+ }
case Sema::NC_Expression:
ConsumeToken(); // the identifier
@@ -211,7 +217,20 @@
if (AnnotateTemplateIdToken(
TemplateTy::make(Classification.getTemplateName()),
Classification.getTemplateNameKind(),
- SS, Id)) {
+ SS, Id, SourceLocation(),
+ /*AllowTypeAnnotation=*/false)) {
+ // Handle errors here by skipping up to the next semicolon or '}', and
+ // eat the semicolon if that's what stopped us.
+ SkipUntil(tok::r_brace, /*StopAtSemi=*/true, /*DontConsume=*/true);
+ if (Tok.is(tok::semi))
+ ConsumeToken();
+ return StmtError();
+ }
+
+ // If the next token is '::', jump right into parsing a
+ // nested-name-specifier. We don't want to leave the template-id
+ // hanging.
+ if (NextToken().is(tok::coloncolon) && TryAnnotateCXXScopeToken(false)){
// Handle errors here by skipping up to the next semicolon or '}', and
// eat the semicolon if that's what stopped us.
SkipUntil(tok::r_brace, /*StopAtSemi=*/true, /*DontConsume=*/true);
Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=130288&r1=130287&r2=130288&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Tue Apr 26 23:48:22 2011
@@ -1255,7 +1255,8 @@
bool Parser::TryAnnotateCXXScopeToken(bool EnteringContext) {
assert(getLang().CPlusPlus &&
"Call sites of this function should be guarded by checking for C++");
- assert((Tok.is(tok::identifier) || Tok.is(tok::coloncolon)) &&
+ assert((Tok.is(tok::identifier) || Tok.is(tok::coloncolon) ||
+ (Tok.is(tok::annot_template_id) && NextToken().is(tok::coloncolon)))&&
"Cannot be a type or scope token!");
CXXScopeSpec SS;
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=130288&r1=130287&r2=130288&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Apr 26 23:48:22 2011
@@ -514,15 +514,16 @@
unsigned QualifiedDiag = diag::err_no_member_suggest;
NamedDecl *FirstDecl = Result.empty()? 0 : *Result.begin();
-
+ NamedDecl *UnderlyingFirstDecl
+ = FirstDecl? FirstDecl->getUnderlyingDecl() : 0;
if (getLangOptions().CPlusPlus && NextToken.is(tok::less) &&
- FirstDecl && isa<TemplateDecl>(FirstDecl)) {
+ UnderlyingFirstDecl && isa<TemplateDecl>(UnderlyingFirstDecl)) {
UnqualifiedDiag = diag::err_no_template_suggest;
QualifiedDiag = diag::err_no_member_template_suggest;
- } else if (FirstDecl &&
- (isa<TypeDecl>(FirstDecl) ||
- isa<ObjCInterfaceDecl>(FirstDecl) ||
- isa<ObjCCompatibleAliasDecl>(FirstDecl))) {
+ } else if (UnderlyingFirstDecl &&
+ (isa<TypeDecl>(UnderlyingFirstDecl) ||
+ isa<ObjCInterfaceDecl>(UnderlyingFirstDecl) ||
+ isa<ObjCCompatibleAliasDecl>(UnderlyingFirstDecl))) {
UnqualifiedDiag = diag::err_unknown_typename_suggest;
QualifiedDiag = diag::err_unknown_nested_typename_suggest;
}
@@ -588,7 +589,8 @@
break;
case LookupResult::Ambiguous:
- if (getLangOptions().CPlusPlus && NextToken.is(tok::less)) {
+ if (getLangOptions().CPlusPlus && NextToken.is(tok::less) &&
+ hasAnyAcceptableTemplateNames(Result)) {
// C++ [temp.local]p3:
// A lookup that finds an injected-class-name (10.2) can result in an
// ambiguity in certain cases (for example, if it is found in more than
@@ -622,37 +624,40 @@
if (!IsFilteredTemplateName)
FilterAcceptableTemplateNames(Result);
- bool IsFunctionTemplate;
- TemplateName Template;
- if (Result.end() - Result.begin() > 1) {
- IsFunctionTemplate = true;
- Template = Context.getOverloadedTemplateName(Result.begin(),
- Result.end());
- } else {
- TemplateDecl *TD = cast<TemplateDecl>(Result.getFoundDecl());
- IsFunctionTemplate = isa<FunctionTemplateDecl>(TD);
-
- if (SS.isSet() && !SS.isInvalid())
- Template = Context.getQualifiedTemplateName(SS.getScopeRep(),
+ if (!Result.empty()) {
+ bool IsFunctionTemplate;
+ TemplateName Template;
+ if (Result.end() - Result.begin() > 1) {
+ IsFunctionTemplate = true;
+ Template = Context.getOverloadedTemplateName(Result.begin(),
+ Result.end());
+ } else {
+ TemplateDecl *TD
+ = cast<TemplateDecl>((*Result.begin())->getUnderlyingDecl());
+ IsFunctionTemplate = isa<FunctionTemplateDecl>(TD);
+
+ if (SS.isSet() && !SS.isInvalid())
+ Template = Context.getQualifiedTemplateName(SS.getScopeRep(),
/*TemplateKeyword=*/false,
- TD);
- else
- Template = TemplateName(TD);
- }
-
- if (IsFunctionTemplate) {
- // Function templates always go through overload resolution, at which
- // point we'll perform the various checks (e.g., accessibility) we need
- // to based on which function we selected.
- Result.suppressDiagnostics();
+ TD);
+ else
+ Template = TemplateName(TD);
+ }
+
+ if (IsFunctionTemplate) {
+ // Function templates always go through overload resolution, at which
+ // point we'll perform the various checks (e.g., accessibility) we need
+ // to based on which function we selected.
+ Result.suppressDiagnostics();
+
+ return NameClassification::FunctionTemplate(Template);
+ }
- return NameClassification::FunctionTemplate(Template);
+ return NameClassification::TypeTemplate(Template);
}
-
- return NameClassification::TypeTemplate(Template);
}
- NamedDecl *FirstDecl = *Result.begin();
+ NamedDecl *FirstDecl = (*Result.begin())->getUnderlyingDecl();
if (TypeDecl *Type = dyn_cast<TypeDecl>(FirstDecl)) {
DiagnoseUseOfDecl(Type, NameLoc);
QualType T = Context.getTypeDeclType(Type);
@@ -681,6 +686,9 @@
return ParsedType::make(T);
}
+ if (!Result.empty() && (*Result.begin())->isCXXClassMember())
+ return BuildPossibleImplicitMemberExpr(SS, Result, 0);
+
bool ADL = UseArgumentDependentLookup(SS, Result, NextToken.is(tok::l_paren));
return BuildDeclarationNameExpr(SS, Result, ADL);
}
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=130288&r1=130287&r2=130288&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Tue Apr 26 23:48:22 2011
@@ -119,7 +119,7 @@
if (isAcceptableTemplateName(Context, *I))
return true;
- return true;
+ return false;
}
TemplateNameKind Sema::isTemplateName(Scope *S,
Modified: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp?rev=130288&r1=130287&r2=130288&view=diff
==============================================================================
--- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp (original)
+++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp Tue Apr 26 23:48:22 2011
@@ -43,8 +43,7 @@
(void)sizeof(auto); // expected-error{{'auto' not allowed here}}
(void)__alignof(auto); // expected-error{{'auto' not allowed here}}
- // FIXME: don't issue the second diagnostic for this error.
- U<auto> v; // expected-error{{'auto' not allowed in template argument}} unexpected-error{{C++ requires a type specifier}}
+ U<auto> v; // expected-error{{'auto' not allowed in template argument}}
int n;
(void)dynamic_cast<auto&>(S()); // expected-error{{'auto' not allowed here}}
Modified: cfe/trunk/test/FixIt/typo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/typo.cpp?rev=130288&r1=130287&r2=130288&view=diff
==============================================================================
--- cfe/trunk/test/FixIt/typo.cpp (original)
+++ cfe/trunk/test/FixIt/typo.cpp Tue Apr 26 23:48:22 2011
@@ -65,3 +65,12 @@
int &Derived::getMember() {
return ember; // expected-error{{use of undeclared identifier 'ember'; did you mean 'member'?}}
}
+
+typedef int Integer; // expected-note{{'Integer' declared here}}
+int global_value; // expected-note{{'global_value' declared here}}
+
+int foo() {
+ integer * i = 0; // expected-error{{unknown type name 'integer'; did you mean 'Integer'?}}
+ unsinged *ptr = 0; // expected-error{{use of undeclared identifier 'unsinged'; did you mean 'unsigned'?}}
+ return *i + *ptr + global_val; // expected-error{{use of undeclared identifier 'global_val'; did you mean 'global_value'?}}
+}
Modified: cfe/trunk/test/SemaCXX/PR9459.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/PR9459.cpp?rev=130288&r1=130287&r2=130288&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/PR9459.cpp (original)
+++ cfe/trunk/test/SemaCXX/PR9459.cpp Tue Apr 26 23:48:22 2011
@@ -2,8 +2,6 @@
// Don't crash.
-template<typename>struct ae_same; // expected-note {{declared here}}
+template<typename>struct ae_same;
template<typename>struct ts{}ap()
-{ts<a>::ap<ae_same<int>::&ae_same<>>::p(a); }; // expected-error 2 {{undeclared identifier}} \
- // expected-error 2 {{expected}} expected-error {{a space is required}} \
- // expected-error 2 {{global}} expected-error {{too few}}
+{ts<a>::ap<ae_same<int>::&ae_same<>>::p(a); }; // expected-error {{use of undeclared identifier 'a'}}
Modified: cfe/trunk/test/SemaTemplate/deduction-crash.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/deduction-crash.cpp?rev=130288&r1=130287&r2=130288&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/deduction-crash.cpp (original)
+++ cfe/trunk/test/SemaTemplate/deduction-crash.cpp Tue Apr 26 23:48:22 2011
@@ -4,7 +4,7 @@
// Note that the error count below doesn't matter. We just want to
// make sure that the parser doesn't crash.
-// CHECK: 14 errors
+// CHECK: 13 errors
template<a>
struct int_;
More information about the cfe-commits
mailing list