forked from OSchip/llvm-project
Make parsing a semantic analysis a little more robust following Sema
failures that involve malformed types, e.g., "typename X::foo" where "foo" isn't a type, or "std::vector<void>" that doens't instantiate properly. Similarly, be a bit smarter in our handling of ambiguities that occur in Sema::getTypeName, to eliminate duplicate error messages about ambiguous name lookup. This eliminates two XFAILs in test/SemaCXX, one of which was crying out to us, trying to tell us that we were producing repeated error messages. llvm-svn: 68251
This commit is contained in:
parent
7182686dbf
commit
fe3d7d0880
|
@ -1005,8 +1005,8 @@ private:
|
|||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// C++ 9: classes [class] and C structs/unions.
|
||||
TypeTy *ParseClassName(SourceLocation &EndLocation,
|
||||
const CXXScopeSpec *SS = 0);
|
||||
TypeResult ParseClassName(SourceLocation &EndLocation,
|
||||
const CXXScopeSpec *SS = 0);
|
||||
void ParseClassSpecifier(DeclSpec &DS,
|
||||
TemplateParameterLists *TemplateParams = 0,
|
||||
AccessSpecifier AS = AS_none);
|
||||
|
@ -1065,7 +1065,7 @@ private:
|
|||
const CXXScopeSpec *SS,
|
||||
SourceLocation TemplateKWLoc = SourceLocation(),
|
||||
bool AllowTypeAnnotation = true);
|
||||
bool AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS = 0);
|
||||
void AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS = 0);
|
||||
bool ParseTemplateArgumentList(TemplateArgList &TemplateArgs,
|
||||
TemplateArgIsTypeList &TemplateArgIsType,
|
||||
TemplateArgLocationList &TemplateArgLocations);
|
||||
|
|
|
@ -558,8 +558,11 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
|
|||
}
|
||||
|
||||
case tok::annot_typename: {
|
||||
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
|
||||
Tok.getAnnotationValue());
|
||||
if (Tok.getAnnotationValue())
|
||||
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
|
||||
Tok.getAnnotationValue());
|
||||
else
|
||||
DS.SetTypeSpecError();
|
||||
DS.SetRangeEnd(Tok.getAnnotationEndLoc());
|
||||
ConsumeToken(); // The typename
|
||||
|
||||
|
@ -648,9 +651,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
|
|||
|
||||
// Turn the template-id annotation token into a type annotation
|
||||
// token, then try again to parse it as a type-specifier.
|
||||
if (AnnotateTemplateIdTokenAsType())
|
||||
DS.SetTypeSpecError();
|
||||
|
||||
AnnotateTemplateIdTokenAsType();
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -915,8 +916,11 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, int& isInvalid,
|
|||
|
||||
// simple-type-specifier:
|
||||
case tok::annot_typename: {
|
||||
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
|
||||
Tok.getAnnotationValue());
|
||||
if (Tok.getAnnotationValue())
|
||||
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
|
||||
Tok.getAnnotationValue());
|
||||
else
|
||||
DS.SetTypeSpecError();
|
||||
DS.SetRangeEnd(Tok.getAnnotationEndLoc());
|
||||
ConsumeToken(); // The typename
|
||||
|
||||
|
@ -1893,11 +1897,11 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
|
|||
// FIXME: Inaccurate.
|
||||
SourceLocation NameLoc = Tok.getLocation();
|
||||
SourceLocation EndLoc;
|
||||
if (TypeTy *Type = ParseClassName(EndLoc)) {
|
||||
D.setDestructor(Type, TildeLoc, NameLoc);
|
||||
} else {
|
||||
TypeResult Type = ParseClassName(EndLoc);
|
||||
if (Type.isInvalid())
|
||||
D.SetIdentifier(0, TildeLoc);
|
||||
}
|
||||
else
|
||||
D.setDestructor(Type.get(), TildeLoc, NameLoc);
|
||||
} else {
|
||||
Diag(Tok, diag::err_expected_class_name);
|
||||
D.SetIdentifier(0, TildeLoc);
|
||||
|
|
|
@ -301,21 +301,23 @@ Parser::DeclPtrTy Parser::ParseStaticAssertDeclaration() {
|
|||
/// identifier
|
||||
/// simple-template-id
|
||||
///
|
||||
Parser::TypeTy *Parser::ParseClassName(SourceLocation &EndLocation,
|
||||
const CXXScopeSpec *SS) {
|
||||
Parser::TypeResult 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_Type_template) {
|
||||
if (AnnotateTemplateIdTokenAsType(SS))
|
||||
return 0;
|
||||
AnnotateTemplateIdTokenAsType(SS);
|
||||
|
||||
assert(Tok.is(tok::annot_typename) && "template-id -> type failed");
|
||||
TypeTy *Type = Tok.getAnnotationValue();
|
||||
EndLocation = Tok.getAnnotationEndLoc();
|
||||
ConsumeToken();
|
||||
return Type;
|
||||
|
||||
if (Type)
|
||||
return Type;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Fall through to produce an error below.
|
||||
|
@ -323,7 +325,7 @@ Parser::TypeTy *Parser::ParseClassName(SourceLocation &EndLocation,
|
|||
|
||||
if (Tok.isNot(tok::identifier)) {
|
||||
Diag(Tok, diag::err_expected_class_name);
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
// We have an identifier; check whether it is actually a type.
|
||||
|
@ -331,7 +333,7 @@ Parser::TypeTy *Parser::ParseClassName(SourceLocation &EndLocation,
|
|||
Tok.getLocation(), CurScope, SS);
|
||||
if (!Type) {
|
||||
Diag(Tok, diag::err_expected_class_name);
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Consume the identifier.
|
||||
|
@ -592,7 +594,7 @@ Parser::BaseResult Parser::ParseBaseSpecifier(DeclPtrTy ClassDecl) {
|
|||
if (IsVirtual) {
|
||||
// Complain about duplicate 'virtual'
|
||||
Diag(VirtualLoc, diag::err_dup_virtual)
|
||||
<< SourceRange(VirtualLoc, VirtualLoc);
|
||||
<< CodeModificationHint::CreateRemoval(SourceRange(VirtualLoc));
|
||||
}
|
||||
|
||||
IsVirtual = true;
|
||||
|
@ -607,8 +609,8 @@ Parser::BaseResult Parser::ParseBaseSpecifier(DeclPtrTy ClassDecl) {
|
|||
|
||||
// Parse the class-name.
|
||||
SourceLocation EndLocation;
|
||||
TypeTy *BaseType = ParseClassName(EndLocation, &SS);
|
||||
if (!BaseType)
|
||||
TypeResult BaseType = ParseClassName(EndLocation, &SS);
|
||||
if (BaseType.isInvalid())
|
||||
return true;
|
||||
|
||||
// Find the complete source range for the base-specifier.
|
||||
|
@ -617,7 +619,7 @@ Parser::BaseResult Parser::ParseBaseSpecifier(DeclPtrTy ClassDecl) {
|
|||
// Notify semantic analysis that we have parsed a complete
|
||||
// base-specifier.
|
||||
return Actions.ActOnBaseSpecifier(ClassDecl, Range, IsVirtual, Access,
|
||||
BaseType, BaseLoc);
|
||||
BaseType.get(), BaseLoc);
|
||||
}
|
||||
|
||||
/// getAccessSpecifierIfPresent - Determine whether the next token is
|
||||
|
|
|
@ -148,12 +148,11 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS) {
|
|||
|
||||
if (TemplateId->Kind == TNK_Type_template ||
|
||||
TemplateId->Kind == TNK_Dependent_template_name) {
|
||||
if (AnnotateTemplateIdTokenAsType(&SS))
|
||||
SS.clear();
|
||||
AnnotateTemplateIdTokenAsType(&SS);
|
||||
SS.clear();
|
||||
|
||||
assert(Tok.is(tok::annot_typename) &&
|
||||
"AnnotateTemplateIdTokenAsType isn't working");
|
||||
|
||||
Token TypeToken = Tok;
|
||||
ConsumeToken();
|
||||
assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!");
|
||||
|
@ -163,12 +162,15 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS) {
|
|||
SS.setBeginLoc(TypeToken.getLocation());
|
||||
HasScopeSpecifier = true;
|
||||
}
|
||||
|
||||
SS.setScopeRep(
|
||||
Actions.ActOnCXXNestedNameSpecifier(CurScope, SS,
|
||||
TypeToken.getAnnotationValue(),
|
||||
TypeToken.getAnnotationRange(),
|
||||
CCLoc));
|
||||
|
||||
if (TypeToken.getAnnotationValue())
|
||||
SS.setScopeRep(
|
||||
Actions.ActOnCXXNestedNameSpecifier(CurScope, SS,
|
||||
TypeToken.getAnnotationValue(),
|
||||
TypeToken.getAnnotationRange(),
|
||||
CCLoc));
|
||||
else
|
||||
SS.setScopeRep(0);
|
||||
SS.setEndLoc(CCLoc);
|
||||
continue;
|
||||
} else
|
||||
|
|
|
@ -588,8 +588,10 @@ void Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
|
|||
/// \brief Replaces a template-id annotation token with a type
|
||||
/// annotation token.
|
||||
///
|
||||
/// \returns true if there was an error, false otherwise.
|
||||
bool Parser::AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS) {
|
||||
/// If there was a failure when forming the type from the template-id,
|
||||
/// a type annotation token will still be created, but will have a
|
||||
/// NULL type pointer to signify an error.
|
||||
void Parser::AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS) {
|
||||
assert(Tok.is(tok::annot_template_id) && "Requires template-id tokens");
|
||||
|
||||
TemplateIdAnnotation *TemplateId
|
||||
|
@ -610,16 +612,9 @@ bool Parser::AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS) {
|
|||
TemplateArgsPtr,
|
||||
TemplateId->getTemplateArgLocations(),
|
||||
TemplateId->RAngleLoc);
|
||||
if (Type.isInvalid()) {
|
||||
// FIXME: better recovery?
|
||||
ConsumeToken();
|
||||
TemplateId->Destroy();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Create the new "type" annotation token.
|
||||
Tok.setKind(tok::annot_typename);
|
||||
Tok.setAnnotationValue(Type.get());
|
||||
Tok.setAnnotationValue(Type.isInvalid()? 0 : Type.get());
|
||||
if (SS && SS->isNotEmpty()) // it was a C++ qualified type name.
|
||||
Tok.setLocation(SS->getBeginLoc());
|
||||
|
||||
|
@ -629,8 +624,6 @@ bool Parser::AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS) {
|
|||
// class template specialization again.
|
||||
PP.ReplaceLastTokenWithAnnotation(Tok);
|
||||
TemplateId->Destroy();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// ParseTemplateArgument - Parse a C++ template argument (C++ [temp.names]).
|
||||
|
|
|
@ -851,22 +851,22 @@ bool Parser::TryAnnotateTypeOrScopeToken() {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (AnnotateTemplateIdTokenAsType(0))
|
||||
return false;
|
||||
|
||||
AnnotateTemplateIdTokenAsType(0);
|
||||
assert(Tok.is(tok::annot_typename) &&
|
||||
"AnnotateTemplateIdTokenAsType isn't working properly");
|
||||
Ty = Actions.ActOnTypenameType(TypenameLoc, SS, SourceLocation(),
|
||||
Tok.getAnnotationValue());
|
||||
if (Tok.getAnnotationValue())
|
||||
Ty = Actions.ActOnTypenameType(TypenameLoc, SS, SourceLocation(),
|
||||
Tok.getAnnotationValue());
|
||||
else
|
||||
Ty = true;
|
||||
} else {
|
||||
Diag(Tok, diag::err_expected_type_name_after_typename)
|
||||
<< SS.getRange();
|
||||
return false;
|
||||
}
|
||||
|
||||
// FIXME: better error recovery!
|
||||
Tok.setKind(tok::annot_typename);
|
||||
Tok.setAnnotationValue(Ty.get());
|
||||
Tok.setAnnotationValue(Ty.isInvalid()? 0 : Ty.get());
|
||||
Tok.setAnnotationEndLoc(Tok.getLocation());
|
||||
Tok.setLocation(TypenameLoc);
|
||||
PP.AnnotateCachedTokens(Tok);
|
||||
|
@ -925,7 +925,8 @@ bool Parser::TryAnnotateTypeOrScopeToken() {
|
|||
// template-id annotation in a context where we weren't allowed
|
||||
// to produce a type annotation token. Update the template-id
|
||||
// annotation token to a type annotation token now.
|
||||
return !AnnotateTemplateIdTokenAsType(&SS);
|
||||
AnnotateTemplateIdTokenAsType(&SS);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -755,7 +755,6 @@ public:
|
|||
/// pointers used to reconstruct new'ed Decl*[] array containing
|
||||
/// found ambiguous decls. LookupResult is owner of this array.
|
||||
AmbiguousLookupStoresDecls
|
||||
|
||||
} StoredKind;
|
||||
|
||||
/// The first lookup result, whose contents depend on the kind of
|
||||
|
@ -939,6 +938,9 @@ public:
|
|||
|
||||
iterator begin();
|
||||
iterator end();
|
||||
|
||||
/// \brief Free the memory associated with this lookup.
|
||||
void Destroy();
|
||||
};
|
||||
|
||||
private:
|
||||
|
|
|
@ -80,9 +80,34 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
|
|||
|
||||
case LookupResult::AmbiguousBaseSubobjectTypes:
|
||||
case LookupResult::AmbiguousBaseSubobjects:
|
||||
case LookupResult::AmbiguousReference:
|
||||
case LookupResult::AmbiguousReference: {
|
||||
// Look to see if we have a type anywhere in the list of results.
|
||||
for (LookupResult::iterator Res = Result.begin(), ResEnd = Result.end();
|
||||
Res != ResEnd; ++Res) {
|
||||
if (isa<TypeDecl>(*Res) || isa<ObjCInterfaceDecl>(*Res)) {
|
||||
IIDecl = *Res;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!IIDecl) {
|
||||
// None of the entities we found is a type, so there is no way
|
||||
// to even assume that the result is a type. In this case, don't
|
||||
// complain about the ambiguity. The parser will either try to
|
||||
// perform this lookup again (e.g., as an object name), which
|
||||
// will produce the ambiguity, or will complain that it expected
|
||||
// a type name.
|
||||
Result.Destroy();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// We found a type within the ambiguous lookup; diagnose the
|
||||
// ambiguity and then return that type. This might be the right
|
||||
// answer, or it might not be, but it suppresses any attempt to
|
||||
// perform the name lookup again.
|
||||
DiagnoseAmbiguousLookup(Result, DeclarationName(&II), NameLoc);
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case LookupResult::Found:
|
||||
IIDecl = Result.getAsDecl();
|
||||
|
@ -3153,7 +3178,7 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK,
|
|||
//
|
||||
// struct S s;
|
||||
//
|
||||
// causes needless err_ovl_no_viable_function_in_init latter.
|
||||
// causes needless "incomplete type" error later.
|
||||
Name = 0;
|
||||
PrevDecl = 0;
|
||||
Invalid = true;
|
||||
|
|
|
@ -25,6 +25,34 @@
|
|||
|
||||
using namespace clang;
|
||||
|
||||
/// \brief Computes the set of declarations referenced by these base
|
||||
/// paths.
|
||||
void BasePaths::ComputeDeclsFound() {
|
||||
assert(NumDeclsFound == 0 && !DeclsFound &&
|
||||
"Already computed the set of declarations");
|
||||
|
||||
std::set<NamedDecl *> Decls;
|
||||
for (BasePaths::paths_iterator Path = begin(), PathEnd = end();
|
||||
Path != PathEnd; ++Path)
|
||||
Decls.insert(*Path->Decls.first);
|
||||
|
||||
NumDeclsFound = Decls.size();
|
||||
DeclsFound = new NamedDecl * [NumDeclsFound];
|
||||
std::copy(Decls.begin(), Decls.end(), DeclsFound);
|
||||
}
|
||||
|
||||
NamedDecl **BasePaths::found_decls_begin() {
|
||||
if (NumDeclsFound == 0)
|
||||
ComputeDeclsFound();
|
||||
return DeclsFound;
|
||||
}
|
||||
|
||||
NamedDecl **BasePaths::found_decls_end() {
|
||||
if (NumDeclsFound == 0)
|
||||
ComputeDeclsFound();
|
||||
return DeclsFound + NumDeclsFound;
|
||||
}
|
||||
|
||||
/// isAmbiguous - Determines whether the set of paths provided is
|
||||
/// ambiguous, i.e., there are two or more paths that refer to
|
||||
/// different base class subobjects of the same type. BaseType must be
|
||||
|
|
|
@ -132,8 +132,16 @@ namespace clang {
|
|||
/// DetectedVirtual - The base class that is virtual.
|
||||
const RecordType *DetectedVirtual;
|
||||
|
||||
/// \brief Array of the declarations that have been found. This
|
||||
/// array is constructed only if needed, e.g., to iterate over the
|
||||
/// results within LookupResult.
|
||||
NamedDecl **DeclsFound;
|
||||
unsigned NumDeclsFound;
|
||||
|
||||
friend class Sema;
|
||||
|
||||
void ComputeDeclsFound();
|
||||
|
||||
public:
|
||||
typedef std::list<BasePath>::const_iterator paths_iterator;
|
||||
|
||||
|
@ -143,15 +151,21 @@ namespace clang {
|
|||
bool RecordPaths = true,
|
||||
bool DetectVirtual = true)
|
||||
: FindAmbiguities(FindAmbiguities), RecordPaths(RecordPaths),
|
||||
DetectVirtual(DetectVirtual), DetectedVirtual(0)
|
||||
DetectVirtual(DetectVirtual), DetectedVirtual(0), DeclsFound(0),
|
||||
NumDeclsFound(0)
|
||||
{}
|
||||
|
||||
~BasePaths() { delete [] DeclsFound; }
|
||||
|
||||
paths_iterator begin() const { return Paths.begin(); }
|
||||
paths_iterator end() const { return Paths.end(); }
|
||||
|
||||
BasePath& front() { return Paths.front(); }
|
||||
const BasePath& front() const { return Paths.front(); }
|
||||
|
||||
NamedDecl **found_decls_begin();
|
||||
NamedDecl **found_decls_end();
|
||||
|
||||
bool isAmbiguous(QualType BaseType);
|
||||
|
||||
/// isFindingAmbiguities - Whether we are finding multiple paths
|
||||
|
|
|
@ -437,13 +437,16 @@ Sema::LookupResult::iterator::operator*() const {
|
|||
case OverloadedDeclFromIdResolver:
|
||||
return *IdentifierResolver::iterator::getFromOpaqueValue(Current);
|
||||
|
||||
case OverloadedDeclFromDeclContext:
|
||||
return *reinterpret_cast<DeclContext::lookup_iterator>(Current);
|
||||
|
||||
case AmbiguousLookupStoresDecls:
|
||||
case AmbiguousLookupStoresBasePaths:
|
||||
assert(false && "Cannot look into ambiguous lookup results");
|
||||
break;
|
||||
if (Result->Last)
|
||||
return *reinterpret_cast<NamedDecl**>(Current);
|
||||
|
||||
// Fall through to handle the DeclContext::lookup_iterator we're
|
||||
// storing.
|
||||
|
||||
case OverloadedDeclFromDeclContext:
|
||||
case AmbiguousLookupStoresDecls:
|
||||
return *reinterpret_cast<DeclContext::lookup_iterator>(Current);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -470,39 +473,90 @@ Sema::LookupResult::iterator& Sema::LookupResult::iterator::operator++() {
|
|||
break;
|
||||
}
|
||||
|
||||
case OverloadedDeclFromDeclContext: {
|
||||
case AmbiguousLookupStoresBasePaths:
|
||||
if (Result->Last) {
|
||||
NamedDecl ** I = reinterpret_cast<NamedDecl**>(Current);
|
||||
++I;
|
||||
Current = reinterpret_cast<uintptr_t>(I);
|
||||
break;
|
||||
}
|
||||
// Fall through to handle the DeclContext::lookup_iterator we're
|
||||
// storing.
|
||||
|
||||
case OverloadedDeclFromDeclContext:
|
||||
case AmbiguousLookupStoresDecls: {
|
||||
DeclContext::lookup_iterator I
|
||||
= reinterpret_cast<DeclContext::lookup_iterator>(Current);
|
||||
++I;
|
||||
Current = reinterpret_cast<uintptr_t>(I);
|
||||
break;
|
||||
}
|
||||
|
||||
case AmbiguousLookupStoresDecls:
|
||||
case AmbiguousLookupStoresBasePaths:
|
||||
assert(false && "Cannot look into ambiguous lookup results");
|
||||
break;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Sema::LookupResult::iterator Sema::LookupResult::begin() {
|
||||
assert(!isAmbiguous() && "Lookup into an ambiguous result");
|
||||
if (StoredKind != OverloadedDeclSingleDecl)
|
||||
switch (StoredKind) {
|
||||
case SingleDecl:
|
||||
case OverloadedDeclFromIdResolver:
|
||||
case OverloadedDeclFromDeclContext:
|
||||
case AmbiguousLookupStoresDecls:
|
||||
return iterator(this, First);
|
||||
OverloadedFunctionDecl * Ovl =
|
||||
reinterpret_cast<OverloadedFunctionDecl*>(First);
|
||||
return iterator(this, reinterpret_cast<uintptr_t>(&(*Ovl->function_begin())));
|
||||
|
||||
case OverloadedDeclSingleDecl: {
|
||||
OverloadedFunctionDecl * Ovl =
|
||||
reinterpret_cast<OverloadedFunctionDecl*>(First);
|
||||
return iterator(this,
|
||||
reinterpret_cast<uintptr_t>(&(*Ovl->function_begin())));
|
||||
}
|
||||
|
||||
case AmbiguousLookupStoresBasePaths:
|
||||
if (Last)
|
||||
return iterator(this,
|
||||
reinterpret_cast<uintptr_t>(getBasePaths()->found_decls_begin()));
|
||||
else
|
||||
return iterator(this,
|
||||
reinterpret_cast<uintptr_t>(getBasePaths()->front().Decls.first));
|
||||
}
|
||||
|
||||
// Required to suppress GCC warning.
|
||||
return iterator();
|
||||
}
|
||||
|
||||
Sema::LookupResult::iterator Sema::LookupResult::end() {
|
||||
assert(!isAmbiguous() && "Lookup into an ambiguous result");
|
||||
if (StoredKind != OverloadedDeclSingleDecl)
|
||||
switch (StoredKind) {
|
||||
case SingleDecl:
|
||||
case OverloadedDeclFromIdResolver:
|
||||
case OverloadedDeclFromDeclContext:
|
||||
case AmbiguousLookupStoresDecls:
|
||||
return iterator(this, Last);
|
||||
OverloadedFunctionDecl * Ovl =
|
||||
reinterpret_cast<OverloadedFunctionDecl*>(First);
|
||||
return iterator(this, reinterpret_cast<uintptr_t>(&(*Ovl->function_end())));
|
||||
|
||||
case OverloadedDeclSingleDecl: {
|
||||
OverloadedFunctionDecl * Ovl =
|
||||
reinterpret_cast<OverloadedFunctionDecl*>(First);
|
||||
return iterator(this,
|
||||
reinterpret_cast<uintptr_t>(&(*Ovl->function_end())));
|
||||
}
|
||||
|
||||
case AmbiguousLookupStoresBasePaths:
|
||||
if (Last)
|
||||
return iterator(this,
|
||||
reinterpret_cast<uintptr_t>(getBasePaths()->found_decls_end()));
|
||||
else
|
||||
return iterator(this, reinterpret_cast<uintptr_t>(
|
||||
getBasePaths()->front().Decls.second));
|
||||
}
|
||||
|
||||
// Required to suppress GCC warning.
|
||||
return iterator();
|
||||
}
|
||||
|
||||
void Sema::LookupResult::Destroy() {
|
||||
if (BasePaths *Paths = getBasePaths())
|
||||
delete Paths;
|
||||
else if (getKind() == AmbiguousReference)
|
||||
delete[] reinterpret_cast<NamedDecl **>(First);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1071,8 +1125,7 @@ bool Sema::DiagnoseAmbiguousLookup(LookupResult &Result, DeclarationName Name,
|
|||
SourceRange LookupRange) {
|
||||
assert(Result.isAmbiguous() && "Lookup result must be ambiguous");
|
||||
|
||||
if (BasePaths *Paths = Result.getBasePaths())
|
||||
{
|
||||
if (BasePaths *Paths = Result.getBasePaths()) {
|
||||
if (Result.getKind() == LookupResult::AmbiguousBaseSubobjects) {
|
||||
QualType SubobjectType = Paths->front().back().Base->getType();
|
||||
Diag(NameLoc, diag::err_ambiguous_member_multiple_subobjects)
|
||||
|
@ -1080,11 +1133,13 @@ bool Sema::DiagnoseAmbiguousLookup(LookupResult &Result, DeclarationName Name,
|
|||
<< LookupRange;
|
||||
|
||||
DeclContext::lookup_iterator Found = Paths->front().Decls.first;
|
||||
while (isa<CXXMethodDecl>(*Found) && cast<CXXMethodDecl>(*Found)->isStatic())
|
||||
while (isa<CXXMethodDecl>(*Found) &&
|
||||
cast<CXXMethodDecl>(*Found)->isStatic())
|
||||
++Found;
|
||||
|
||||
Diag((*Found)->getLocation(), diag::note_ambiguous_member_found);
|
||||
|
||||
Result.Destroy();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1102,20 +1157,18 @@ bool Sema::DiagnoseAmbiguousLookup(LookupResult &Result, DeclarationName Name,
|
|||
Diag(D->getLocation(), diag::note_ambiguous_member_found);
|
||||
}
|
||||
|
||||
delete Paths;
|
||||
Result.Destroy();
|
||||
return true;
|
||||
} else if (Result.getKind() == LookupResult::AmbiguousReference) {
|
||||
|
||||
Diag(NameLoc, diag::err_ambiguous_reference) << Name << LookupRange;
|
||||
|
||||
NamedDecl **DI = reinterpret_cast<NamedDecl **>(Result.First),
|
||||
**DEnd = reinterpret_cast<NamedDecl **>(Result.Last);
|
||||
**DEnd = reinterpret_cast<NamedDecl **>(Result.Last);
|
||||
|
||||
for (; DI != DEnd; ++DI)
|
||||
Diag((*DI)->getLocation(), diag::note_ambiguous_candidate) << *DI;
|
||||
|
||||
delete[] reinterpret_cast<NamedDecl **>(Result.First);
|
||||
|
||||
Result.Destroy();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1466,7 +1519,6 @@ void Sema::ArgumentDependentLookup(DeclarationName Name,
|
|||
AssociatedNamespaces, AssociatedClasses);
|
||||
|
||||
// C++ [basic.lookup.argdep]p3:
|
||||
//
|
||||
// Let X be the lookup set produced by unqualified lookup (3.4.1)
|
||||
// and let Y be the lookup set produced by argument dependent
|
||||
// lookup (defined as follows). If X contains [...] then Y is
|
||||
|
|
|
@ -870,8 +870,11 @@ Sema::ActOnTemplateIdType(TemplateTy TemplateD, SourceLocation TemplateLoc,
|
|||
QualType Result = CheckTemplateIdType(Template, TemplateLoc, LAngleLoc,
|
||||
&TemplateArgs[0], TemplateArgs.size(),
|
||||
RAngleLoc);
|
||||
|
||||
TemplateArgsIn.release();
|
||||
|
||||
if (Result.isNull())
|
||||
return true;
|
||||
|
||||
return Result.getAsOpaquePtr();
|
||||
}
|
||||
|
||||
|
@ -2102,6 +2105,8 @@ Sema::ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS,
|
|||
return true;
|
||||
|
||||
QualType T = CheckTypenameType(NNS, II, SourceRange(TypenameLoc, IdLoc));
|
||||
if (T.isNull())
|
||||
return true;
|
||||
return T.getAsOpaquePtr();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,36 +1,33 @@
|
|||
// RUN: clang-cc -fsyntax-only -verify %s
|
||||
// XFAIL
|
||||
// fails due to exact diagnostic matching
|
||||
|
||||
struct A {
|
||||
int a; // expected-note{{member found by ambiguous name lookup}}
|
||||
int a; // expected-note 4{{member found by ambiguous name lookup}}
|
||||
static int b;
|
||||
static int c; // expected-note{{member found by ambiguous name lookup}}
|
||||
static int c; // expected-note 4{{member found by ambiguous name lookup}}
|
||||
|
||||
enum E { enumerator };
|
||||
|
||||
typedef int type;
|
||||
|
||||
static void f(int);
|
||||
void f(float); // expected-note{{member found by ambiguous name lookup}}
|
||||
void f(float); // expected-note 2{{member found by ambiguous name lookup}}
|
||||
|
||||
static void static_f(int);
|
||||
static void static_f(double);
|
||||
};
|
||||
|
||||
struct B : A {
|
||||
int d; // expected-note{{member found by ambiguous name lookup}}
|
||||
int d; // expected-note 2{{member found by ambiguous name lookup}}
|
||||
|
||||
enum E2 { enumerator2 };
|
||||
|
||||
enum E3 { enumerator3 }; // expected-note{{member found by ambiguous name lookup}}
|
||||
enum E3 { enumerator3 }; // expected-note 2{{member found by ambiguous name lookup}}
|
||||
};
|
||||
|
||||
struct C : A {
|
||||
int c; // expected-note{{member found by ambiguous name lookup}}
|
||||
int d; // expected-note{{member found by ambiguous name lookup}}
|
||||
int c; // expected-note 2{{member found by ambiguous name lookup}}
|
||||
int d; // expected-note 2{{member found by ambiguous name lookup}}
|
||||
|
||||
enum E3 { enumerator3_2 }; // expected-note{{member found by ambiguous name lookup}}
|
||||
enum E3 { enumerator3_2 }; // expected-note 2{{member found by ambiguous name lookup}}
|
||||
};
|
||||
|
||||
struct D : B, C {
|
||||
|
@ -50,7 +47,7 @@ void test_lookup(D d) {
|
|||
|
||||
D::E2 e2 = D::enumerator2; // okay
|
||||
|
||||
D::E3 e3; // expected-error{{member 'E3' found in multiple base classes of different types}}
|
||||
D::E3 e3; // expected-error{{multiple base classes}}
|
||||
}
|
||||
|
||||
void D::test_lookup() {
|
||||
|
@ -70,18 +67,18 @@ void D::test_lookup() {
|
|||
}
|
||||
|
||||
struct B2 : virtual A {
|
||||
int d; // expected-note{{member found by ambiguous name lookup}}
|
||||
int d; // expected-note 2{{member found by ambiguous name lookup}}
|
||||
|
||||
enum E2 { enumerator2 };
|
||||
|
||||
enum E3 { enumerator3 }; // expected-note{{member found by ambiguous name lookup}}
|
||||
enum E3 { enumerator3 }; // expected-note 2 {{member found by ambiguous name lookup}}
|
||||
};
|
||||
|
||||
struct C2 : virtual A {
|
||||
int c; // expected-note{{member found by ambiguous name lookup}}
|
||||
int d; // expected-note{{member found by ambiguous name lookup}}
|
||||
int c; // expected-note 2{{member found by ambiguous name lookup}}
|
||||
int d; // expected-note 2{{member found by ambiguous name lookup}}
|
||||
|
||||
enum E3 { enumerator3_2 }; // expected-note{{member found by ambiguous name lookup}}
|
||||
enum E3 { enumerator3_2 }; // expected-note 2{{member found by ambiguous name lookup}}
|
||||
};
|
||||
|
||||
struct D2 : B2, C2 {
|
||||
|
@ -147,6 +144,5 @@ struct HasAnotherMemberType : HasMemberType1, HasMemberType2 {
|
|||
};
|
||||
|
||||
struct UsesAmbigMemberType : HasMemberType1, HasMemberType2 {
|
||||
type t; // expected-error{{member 'type' found in multiple base classes of different types}} \
|
||||
// expected-error{{expected ';' at end of declaration list}}
|
||||
type t; // expected-error{{member 'type' found in multiple base classes of different types}}
|
||||
};
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
// RUN: clang-cc -fsyntax-only -verify %s
|
||||
// XFAIL
|
||||
// fails due to exact diagnostic matching
|
||||
|
||||
namespace A {
|
||||
short i; // expected-note{{candidate found by name lookup is 'A::i'}}
|
||||
short i; // expected-note 2{{candidate found by name lookup is 'A::i'}}
|
||||
namespace B {
|
||||
long i; // expected-note{{candidate found by name lookup is 'A::B::i'}}
|
||||
void f() {} // expected-note{{candidate function}}
|
||||
|
@ -58,7 +56,7 @@ void K1::foo() {} // okay
|
|||
|
||||
// FIXME: Do we want err_ovl_no_viable_function_in_init here?
|
||||
struct K2 k2; // expected-error{{reference to 'K2' is ambiguous}} \
|
||||
expected-error{{no matching constructor}}
|
||||
expected-error{{incomplete type}}
|
||||
|
||||
// FIXME: This case is incorrectly diagnosed!
|
||||
//K2 k3;
|
||||
|
@ -66,7 +64,7 @@ struct K2 k2; // expected-error{{reference to 'K2' is ambiguous}} \
|
|||
|
||||
class X { // expected-note{{candidate found by name lookup is 'X'}}
|
||||
// FIXME: produce a suitable error message for this
|
||||
using namespace A; // expected-error{{expected unqualified-id}}
|
||||
using namespace A; // expected-error{{expected member name or}}
|
||||
};
|
||||
|
||||
namespace N {
|
||||
|
@ -96,7 +94,8 @@ namespace OneFunction {
|
|||
}
|
||||
|
||||
namespace TwoTag {
|
||||
struct X; // expected-note{{candidate found by name lookup is 'TwoTag::X'}}
|
||||
struct X; // expected-note{{candidate found by name lookup is 'TwoTag::X'}} \
|
||||
// expected-note{{forward declaration}}
|
||||
}
|
||||
|
||||
namespace FuncHidesTagAmbiguity {
|
||||
|
@ -105,6 +104,7 @@ namespace FuncHidesTagAmbiguity {
|
|||
using namespace TwoTag;
|
||||
|
||||
void test() {
|
||||
(void)X(); // expected-error{{reference to 'X' is ambiguous}}
|
||||
(void)X(); // expected-error{{reference to 'X' is ambiguous}} \
|
||||
// FIXME: expected-error{{invalid use of incomplete type}}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ struct ::N::A<int>::X {
|
|||
|
||||
#if 0
|
||||
// FIXME: the following crashes the parser, because Sema has no way to
|
||||
// community that the "dependent" template-name N::template B doesn't
|
||||
// communicate that the "dependent" template-name N::template B doesn't
|
||||
// actually refer to a template.
|
||||
template<typename T>
|
||||
struct TestA {
|
||||
|
|
Loading…
Reference in New Issue