forked from OSchip/llvm-project
revert my previous patch, it is breaking something and I don't have time
to fix it ATM. llvm-svn: 90717
This commit is contained in:
parent
71a26d8f82
commit
ed085234dc
|
@ -166,8 +166,6 @@ def err_use_of_tag_name_without_tag : Error<
|
|||
"use of tagged type %0 without '%1' tag">;
|
||||
def err_expected_ident_in_using : Error<
|
||||
"expected an identifier in using directive">;
|
||||
def err_unexected_colon_in_nested_name_spec : Error<
|
||||
"unexpected ':' in nested name specifier">;
|
||||
|
||||
/// Objective-C parser diagnostics
|
||||
def err_objc_no_attributes_on_category : Error<
|
||||
|
|
|
@ -334,20 +334,6 @@ public:
|
|||
bool EnteringContext) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// IsInvalidUnlessNestedName - This method is used for error recovery
|
||||
/// purposes to determine whether the specified identifier is only valid as
|
||||
/// a nested name specifier, for example a namespace name. It is
|
||||
/// conservatively correct to always return false from this method.
|
||||
///
|
||||
/// The arguments are the same as those passed to ActOnCXXNestedNameSpecifier.
|
||||
virtual bool IsInvalidUnlessNestedName(Scope *S,
|
||||
const CXXScopeSpec &SS,
|
||||
IdentifierInfo &II,
|
||||
TypeTy *ObjectType,
|
||||
bool EnteringContext) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// ActOnCXXNestedNameSpecifier - Called during parsing of a
|
||||
/// nested-name-specifier that involves a template-id, e.g.,
|
||||
|
|
|
@ -887,8 +887,7 @@ private:
|
|||
|
||||
bool ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
|
||||
TypeTy *ObjectType,
|
||||
bool EnteringContext,
|
||||
bool ColonIsSacred = false);
|
||||
bool EnteringContext);
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// C++ 5.2p1: C++ Casts
|
||||
|
|
|
@ -132,7 +132,7 @@ Parser::DeclPtrTy Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc,
|
|||
|
||||
CXXScopeSpec SS;
|
||||
// Parse (optional) nested-name-specifier.
|
||||
ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false, false);
|
||||
ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
|
||||
|
||||
if (SS.isInvalid() || Tok.isNot(tok::identifier)) {
|
||||
Diag(Tok, diag::err_expected_namespace_name);
|
||||
|
@ -260,7 +260,7 @@ Parser::DeclPtrTy Parser::ParseUsingDirective(unsigned Context,
|
|||
|
||||
CXXScopeSpec SS;
|
||||
// Parse (optional) nested-name-specifier.
|
||||
ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false, false);
|
||||
ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
|
||||
|
||||
IdentifierInfo *NamespcName = 0;
|
||||
SourceLocation IdentLoc = SourceLocation();
|
||||
|
@ -322,7 +322,7 @@ Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context,
|
|||
IsTypeName = false;
|
||||
|
||||
// Parse nested-name-specifier.
|
||||
ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false, false);
|
||||
ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
|
||||
|
||||
AttributeList *AttrList = 0;
|
||||
|
||||
|
@ -601,7 +601,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
|
|||
// Parse the (optional) nested-name-specifier.
|
||||
CXXScopeSpec SS;
|
||||
if (getLang().CPlusPlus &&
|
||||
ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, true, true))
|
||||
ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, true))
|
||||
if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id))
|
||||
Diag(Tok, diag::err_expected_ident);
|
||||
|
||||
|
|
|
@ -45,14 +45,10 @@ using namespace clang;
|
|||
/// \param EnteringContext whether we will be entering into the context of
|
||||
/// the nested-name-specifier after parsing it.
|
||||
///
|
||||
/// \param ColonIsSacred - If this is true, then a colon is valid after the
|
||||
/// specifier, so we should not try to recover from colons aggressively.
|
||||
///
|
||||
/// \returns true if a scope specifier was parsed.
|
||||
bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
|
||||
Action::TypeTy *ObjectType,
|
||||
bool EnteringContext,
|
||||
bool ColonIsSacred) {
|
||||
bool EnteringContext) {
|
||||
assert(getLang().CPlusPlus &&
|
||||
"Call sites of this function should be guarded by checking for C++");
|
||||
|
||||
|
@ -218,29 +214,11 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
|
|||
// namespace-name '::'
|
||||
// nested-name-specifier identifier '::'
|
||||
Token Next = NextToken();
|
||||
|
||||
// If we get foo:bar, this is almost certainly a typo for foo::bar. Recover
|
||||
// and emit a fixit hint for it.
|
||||
if (Next.is(tok::colon) && !ColonIsSacred &&
|
||||
Actions.IsInvalidUnlessNestedName(CurScope, SS, II, ObjectType,
|
||||
EnteringContext) &&
|
||||
// If the token after the colon isn't an identifier, it's still an
|
||||
// error, but they probably meant something else strange so don't
|
||||
// recover like this.
|
||||
PP.LookAhead(1).is(tok::identifier)) {
|
||||
Diag(Next, diag::err_unexected_colon_in_nested_name_spec)
|
||||
<< CodeModificationHint::CreateReplacement(Next.getLocation(), "::");
|
||||
|
||||
// Recover as if the user wrote '::'.
|
||||
Next.setKind(tok::coloncolon);
|
||||
}
|
||||
|
||||
if (Next.is(tok::coloncolon)) {
|
||||
// We have an identifier followed by a '::'. Lookup this name
|
||||
// as the name in a nested-name-specifier.
|
||||
SourceLocation IdLoc = ConsumeToken();
|
||||
assert((Tok.is(tok::coloncolon) || Tok.is(tok::colon)) &&
|
||||
"NextToken() not working properly!");
|
||||
assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!");
|
||||
SourceLocation CCLoc = ConsumeToken();
|
||||
|
||||
if (!HasScopeSpecifier) {
|
||||
|
|
|
@ -2000,8 +2000,7 @@ public:
|
|||
IdentifierInfo &II,
|
||||
QualType ObjectType,
|
||||
NamedDecl *ScopeLookupResult,
|
||||
bool EnteringContext,
|
||||
bool EmitNoDiagnostics);
|
||||
bool EnteringContext);
|
||||
|
||||
virtual CXXScopeTy *ActOnCXXNestedNameSpecifier(Scope *S,
|
||||
const CXXScopeSpec &SS,
|
||||
|
@ -2011,12 +2010,6 @@ public:
|
|||
TypeTy *ObjectType,
|
||||
bool EnteringContext);
|
||||
|
||||
virtual bool IsInvalidUnlessNestedName(Scope *S,
|
||||
const CXXScopeSpec &SS,
|
||||
IdentifierInfo &II,
|
||||
TypeTy *ObjectType,
|
||||
bool EnteringContext);
|
||||
|
||||
/// ActOnCXXNestedNameSpecifier - Called during parsing of a
|
||||
/// nested-name-specifier that involves a template-id, e.g.,
|
||||
/// "foo::bar<int, float>::", and now we need to build a scope
|
||||
|
|
|
@ -330,9 +330,6 @@ NamedDecl *Sema::FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS) {
|
|||
/// that it contains an extra parameter \p ScopeLookupResult, which provides
|
||||
/// the result of name lookup within the scope of the nested-name-specifier
|
||||
/// that was computed at template definitino time.
|
||||
///
|
||||
/// If EmitNoDiagnostics is true, this should not emit diagnostics, it should
|
||||
/// just return null on failure.
|
||||
Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S,
|
||||
const CXXScopeSpec &SS,
|
||||
SourceLocation IdLoc,
|
||||
|
@ -340,8 +337,7 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S,
|
|||
IdentifierInfo &II,
|
||||
QualType ObjectType,
|
||||
NamedDecl *ScopeLookupResult,
|
||||
bool EnteringContext,
|
||||
bool EmitNoDiagnostics) {
|
||||
bool EnteringContext) {
|
||||
NestedNameSpecifier *Prefix
|
||||
= static_cast<NestedNameSpecifier *>(SS.getScopeRep());
|
||||
|
||||
|
@ -446,17 +442,14 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S,
|
|||
!Context.hasSameType(
|
||||
Context.getTypeDeclType(cast<TypeDecl>(OuterDecl)),
|
||||
Context.getTypeDeclType(cast<TypeDecl>(SD))))) {
|
||||
if (EmitNoDiagnostics)
|
||||
return 0;
|
||||
|
||||
Diag(IdLoc, diag::err_nested_name_member_ref_lookup_ambiguous)
|
||||
<< &II;
|
||||
Diag(SD->getLocation(), diag::note_ambig_member_ref_object_type)
|
||||
<< ObjectType;
|
||||
Diag(OuterDecl->getLocation(), diag::note_ambig_member_ref_scope);
|
||||
|
||||
// Fall through so that we'll pick the name we found in the object
|
||||
// type, since that's probably what the user wanted anyway.
|
||||
// Fall through so that we'll pick the name we found in the object type,
|
||||
// since that's probably what the user wanted anyway.
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -476,11 +469,6 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S,
|
|||
T.getTypePtr());
|
||||
}
|
||||
|
||||
// Otherwise, we have an error case. If we don't want diagnostics, just
|
||||
// return an error now.
|
||||
if (EmitNoDiagnostics)
|
||||
return 0;
|
||||
|
||||
// If we didn't find anything during our lookup, try again with
|
||||
// ordinary name lookup, which can help us produce better error
|
||||
// messages.
|
||||
|
@ -521,23 +509,7 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S,
|
|||
bool EnteringContext) {
|
||||
return BuildCXXNestedNameSpecifier(S, SS, IdLoc, CCLoc, II,
|
||||
QualType::getFromOpaquePtr(ObjectTypePtr),
|
||||
/*ScopeLookupResult=*/0, EnteringContext,
|
||||
false);
|
||||
}
|
||||
|
||||
/// IsInvalidUnlessNestedName - This method is used for error recovery
|
||||
/// purposes to determine whether the specified identifier is only valid as
|
||||
/// a nested name specifier, for example a namespace name. It is
|
||||
/// conservatively correct to always return false from this method.
|
||||
///
|
||||
/// The arguments are the same as those passed to ActOnCXXNestedNameSpecifier.
|
||||
bool Sema::IsInvalidUnlessNestedName(Scope *S, const CXXScopeSpec &SS,
|
||||
IdentifierInfo &II, TypeTy *ObjectType,
|
||||
bool EnteringContext) {
|
||||
return BuildCXXNestedNameSpecifier(S, SS, SourceLocation(), SourceLocation(),
|
||||
II, QualType::getFromOpaquePtr(ObjectType),
|
||||
/*ScopeLookupResult=*/0, EnteringContext,
|
||||
true);
|
||||
/*ScopeLookupResult=*/0, EnteringContext);
|
||||
}
|
||||
|
||||
Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S,
|
||||
|
|
|
@ -5407,7 +5407,7 @@ TreeTransform<Derived>::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
|
|||
Range.getEnd(), II,
|
||||
ObjectType,
|
||||
FirstQualifierInScope,
|
||||
false, false));
|
||||
false));
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
|
|
|
@ -1,24 +1,3 @@
|
|||
// RUN: clang-cc -verify -fsyntax-only %s
|
||||
|
||||
int x(*g); // expected-error {{use of undeclared identifier 'g'}}
|
||||
|
||||
|
||||
// PR4451 - We should recover well from the typo of '::' as ':' in a2.
|
||||
namespace y {
|
||||
struct a { };
|
||||
}
|
||||
|
||||
y::a a1;
|
||||
y:a a2; // expected-error {{unexpected ':' in nested name specifier}}
|
||||
y::a a3 = a2;
|
||||
|
||||
// Some valid colons:
|
||||
void foo() {
|
||||
y: // label
|
||||
y::a s;
|
||||
|
||||
int a = 4;
|
||||
a = a ? a : a+1;
|
||||
}
|
||||
|
||||
struct b : y::a {};
|
|
@ -186,10 +186,12 @@ class foo {
|
|||
};
|
||||
|
||||
|
||||
// PR4452 / PR4451
|
||||
foo<somens:a> a2; // expected-error {{unexpected ':' in nested name specifier}}
|
||||
// PR4452
|
||||
// FIXME: This error recovery sucks.
|
||||
foo<somens:a> a2; // expected-error {{unexpected namespace name 'somens': expected expression}} \
|
||||
expected-error {{C++ requires a type specifier for all declarations}}
|
||||
|
||||
somens::a a3 = a2; // expected-error {{cannot initialize 'a3' with an lvalue of type 'foo<somens::a>'}}
|
||||
somens::a a3 = a2;
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue