aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Parse/ParseStmt.cpp29
-rw-r--r--lib/Parse/Parser.cpp3
-rw-r--r--lib/Sema/SemaDecl.cpp74
-rw-r--r--lib/Sema/SemaTemplate.cpp2
-rw-r--r--test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp3
-rw-r--r--test/FixIt/typo.cpp9
-rw-r--r--test/SemaCXX/PR9459.cpp6
-rw-r--r--test/SemaTemplate/deduction-crash.cpp2
8 files changed, 81 insertions, 47 deletions
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index a324bdc045..3aec4ea210 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -113,7 +113,7 @@ Retry:
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 @@ Retry:
// 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 @@ Retry:
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 @@ Retry:
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);
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index debc7404b9..ee4ef4263a 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -1255,7 +1255,8 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {
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;
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 200082f17b..f589b2d4a9 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -514,15 +514,16 @@ Corrected:
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 @@ Corrected:
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 @@ Corrected:
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 @@ Corrected:
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);
}
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 3123f5fc67..3deeedc90d 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -119,7 +119,7 @@ bool Sema::hasAnyAcceptableTemplateNames(LookupResult &R) {
if (isAcceptableTemplateName(Context, *I))
return true;
- return true;
+ return false;
}
TemplateNameKind Sema::isTemplateName(Scope *S,
diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp
index c00d4b7023..09245cfd20 100644
--- a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp
+++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp
@@ -43,8 +43,7 @@ void j() {
(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}}
diff --git a/test/FixIt/typo.cpp b/test/FixIt/typo.cpp
index 440db45518..f8b5352374 100644
--- a/test/FixIt/typo.cpp
+++ b/test/FixIt/typo.cpp
@@ -65,3 +65,12 @@ struct Derived : public Base { // expected-note{{base class 'Base' specified her
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'?}}
+}
diff --git a/test/SemaCXX/PR9459.cpp b/test/SemaCXX/PR9459.cpp
index 33cb2e5bc2..dfb242dc59 100644
--- a/test/SemaCXX/PR9459.cpp
+++ b/test/SemaCXX/PR9459.cpp
@@ -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'}}
diff --git a/test/SemaTemplate/deduction-crash.cpp b/test/SemaTemplate/deduction-crash.cpp
index 8a15605734..ec97311e5d 100644
--- a/test/SemaTemplate/deduction-crash.cpp
+++ b/test/SemaTemplate/deduction-crash.cpp
@@ -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_;