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();
// 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();
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
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);
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;
}
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
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);
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);
}