Add support for C++ namespace-aware typo correction, e.g., correcting

vector<int>

to

  std::vector<int>

Patch by Kaelyn Uhrain, with minor tweaks + PCH support from me. Fixes
PR5776/<rdar://problem/8652971>.

Thanks Kaelyn!

llvm-svn: 134007
This commit is contained in:
Douglas Gregor 2011-06-28 16:20:02 +00:00
parent d79f9666c8
commit c2fa169d6c
25 changed files with 1072 additions and 529 deletions

View File

@ -49,6 +49,11 @@ public:
/// instance and factory methods, respectively, with this selector.
virtual std::pair<ObjCMethodList,ObjCMethodList> ReadMethodPool(Selector Sel);
/// \brief Load the set of namespaces that are known to the external source,
/// which will be used during typo correction.
virtual void ReadKnownNamespaces(
llvm::SmallVectorImpl<NamespaceDecl *> &Namespaces);
/// \brief Do last resort, unqualified lookup on a LookupResult that
/// Sema cannot find.
///

View File

@ -21,6 +21,7 @@
#include "clang/Sema/ObjCMethodList.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/LocInfoType.h"
#include "clang/Sema/TypoCorrection.h"
#include "clang/AST/Expr.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/ExternalASTSource.h"
@ -46,6 +47,8 @@ namespace clang {
class ASTConsumer;
class ASTContext;
class ASTMutationListener;
class ASTReader;
class ASTWriter;
class ArrayType;
class AttributeList;
class BlockDecl;
@ -1623,6 +1626,16 @@ private:
bool ConstThis,
bool VolatileThis);
// \brief The set of known/encountered (unique, canonicalized) NamespaceDecls.
//
// The boolean value will be true to indicate that the namespace was loaded
// from an AST/PCH file, or false otherwise.
llvm::DenseMap<NamespaceDecl*, bool> KnownNamespaces;
/// \brief Whether we have already loaded known namespaces from an extenal
/// source.
bool LoadedExternalKnownNamespaces;
public:
/// \brief Look up a name, looking for a single declaration. Return
/// null if the results were absent, ambiguous, or overloaded.
@ -1699,11 +1712,13 @@ public:
CTC_ObjCMessageReceiver
};
DeclarationName CorrectTypo(LookupResult &R, Scope *S, CXXScopeSpec *SS,
DeclContext *MemberContext = 0,
bool EnteringContext = false,
CorrectTypoContext CTC = CTC_Unknown,
const ObjCObjectPointerType *OPT = 0);
TypoCorrection CorrectTypo(const DeclarationNameInfo &Typo,
Sema::LookupNameKind LookupKind,
Scope *S, CXXScopeSpec *SS,
DeclContext *MemberContext = NULL,
bool EnteringContext = false,
CorrectTypoContext CTC = CTC_Unknown,
const ObjCObjectPointerType *OPT = NULL);
void FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs,
AssociatedNamespaceSet &AssociatedNamespaces,
@ -4721,7 +4736,7 @@ public:
/// \brief The number of typos corrected by CorrectTypo.
unsigned TyposCorrected;
typedef llvm::DenseMap<IdentifierInfo *, std::pair<llvm::StringRef, bool> >
typedef llvm::DenseMap<IdentifierInfo *, TypoCorrection>
UnqualifiedTyposCorrectedMap;
/// \brief A cache containing the results of typo correction for unqualified
@ -5918,6 +5933,8 @@ private:
protected:
friend class Parser;
friend class InitializationSequence;
friend class ASTReader;
friend class ASTWriter;
public:
/// \brief Retrieve the parser's current scope.

View File

@ -0,0 +1,105 @@
//===--- TypoCorrection.h - Class for typo correction results ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the TypoCorrection class, which stores the results of
// Sema's typo correction (Sema::CorrectTypo).
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_SEMA_TYPOCORRECTION_H
#define LLVM_CLANG_SEMA_TYPOCORRECTION_H
#include "clang/AST/DeclCXX.h"
namespace clang {
/// @brief Simple class containing the result of Sema::CorrectTypo
class TypoCorrection {
public:
TypoCorrection(const DeclarationName &Name, NamedDecl *NameDecl,
NestedNameSpecifier *NNS=NULL, unsigned distance=0)
: CorrectionName(Name),
CorrectionNameSpec(NNS),
CorrectionDecl(NameDecl),
EditDistance(distance) {}
TypoCorrection(NamedDecl *Name, NestedNameSpecifier *NNS=NULL,
unsigned distance=0)
: CorrectionName(Name->getDeclName()),
CorrectionNameSpec(NNS),
CorrectionDecl(Name),
EditDistance(distance) {}
TypoCorrection(DeclarationName Name, NestedNameSpecifier *NNS=NULL,
unsigned distance=0)
: CorrectionName(Name),
CorrectionNameSpec(NNS),
CorrectionDecl(NULL),
EditDistance(distance) {}
TypoCorrection()
: CorrectionName(), CorrectionNameSpec(NULL), CorrectionDecl(NULL),
EditDistance(0) {}
/// \brief Gets the DeclarationName of the typo correction
DeclarationName getCorrection() const { return CorrectionName; }
IdentifierInfo* getCorrectionAsIdentifierInfo() const {
return CorrectionName.getAsIdentifierInfo();
}
/// \brief Gets the NestedNameSpecifier needed to use the typo correction
NestedNameSpecifier* getCorrectionSpecifier() const {
return CorrectionNameSpec;
}
void setCorrectionSpecifier(NestedNameSpecifier* NNS) {
CorrectionNameSpec = NNS;
}
/// \brief Gets the "edit distance" of the typo correction from the typo
unsigned getEditDistance() const { return EditDistance; }
/// \brief Gets the pointer to the declaration of the typo correction
NamedDecl* getCorrectionDecl() const {
return isKeyword() ? NULL : CorrectionDecl;
}
template <class DeclClass>
DeclClass *getCorrectionDeclAs() const {
return dyn_cast_or_null<DeclClass>(getCorrectionDecl());
}
void setCorrectionDecl(NamedDecl *CDecl) {
CorrectionDecl = CDecl;
if (!CorrectionName)
CorrectionName = CDecl->getDeclName();
}
std::string getAsString(const LangOptions &LO) const;
std::string getQuoted(const LangOptions &LO) const {
return "'" + getAsString(LO) + "'";
}
operator bool() const { return bool(CorrectionName); }
static inline NamedDecl *KeywordDecl() { return (NamedDecl*)-1; }
bool isKeyword() const { return CorrectionDecl == KeywordDecl(); }
// Returns true if the correction either is a keyword or has a known decl.
bool isResolved() const { return CorrectionDecl != NULL; }
private:
// Results.
DeclarationName CorrectionName;
NestedNameSpecifier *CorrectionNameSpec;
NamedDecl *CorrectionDecl;
unsigned EditDistance;
};
}
#endif

View File

@ -371,7 +371,11 @@ namespace clang {
/// \brief Record code for the table of offsets into the block
/// of file source-location information.
FILE_SOURCE_LOCATION_OFFSETS = 45
FILE_SOURCE_LOCATION_OFFSETS = 45,
/// \brief Record code for the set of known namespaces, which are used
/// for typo correction.
KNOWN_NAMESPACES = 46
};

View File

@ -625,6 +625,9 @@ private:
/// \brief The OpenCL extension settings.
llvm::SmallVector<uint64_t, 1> OpenCLExtensions;
/// \brief A list of the namespaces we've seen.
llvm::SmallVector<uint64_t, 4> KnownNamespaces;
//@}
/// \brief Diagnostic IDs and their mappings that the user changed.
@ -1125,6 +1128,11 @@ public:
virtual std::pair<ObjCMethodList, ObjCMethodList>
ReadMethodPool(Selector Sel);
/// \brief Load the set of namespaces that are known to the external source,
/// which will be used during typo correction.
virtual void ReadKnownNamespaces(
llvm::SmallVectorImpl<NamespaceDecl *> &Namespaces);
/// \brief Load a selector from disk, registering its ID if it exists.
void LoadSelector(Selector Sel);

View File

@ -154,6 +154,8 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
AnalysisWarnings(*this)
{
TUScope = 0;
LoadedExternalKnownNamespaces = false;
if (getLangOptions().CPlusPlus)
FieldCollector.reset(new CXXFieldCollector());
@ -778,6 +780,10 @@ ExternalSemaSource::ReadMethodPool(Selector Sel) {
return std::pair<ObjCMethodList, ObjCMethodList>();
}
void ExternalSemaSource::ReadKnownNamespaces(
llvm::SmallVectorImpl<NamespaceDecl *> &Namespaces) {
}
void PrettyDeclStackTraceEntry::print(llvm::raw_ostream &OS) const {
SourceLocation Loc = this->Loc;
if (!Loc.isValid() && TheDecl) Loc = TheDecl->getLocation();

View File

@ -464,26 +464,29 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
// We haven't found anything, and we're not recovering from a
// different kind of error, so look for typos.
DeclarationName Name = Found.getLookupName();
if (CorrectTypo(Found, S, &SS, LookupCtx, EnteringContext,
CTC_NoKeywords) &&
Found.isSingleResult() &&
isAcceptableNestedNameSpecifier(Found.getAsSingle<NamedDecl>())) {
TypoCorrection Corrected;
Found.clear();
if ((Corrected = CorrectTypo(Found.getLookupNameInfo(),
Found.getLookupKind(), S, &SS, LookupCtx,
EnteringContext, CTC_NoKeywords)) &&
isAcceptableNestedNameSpecifier(Corrected.getCorrectionDecl())) {
std::string CorrectedStr(Corrected.getAsString(getLangOptions()));
std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOptions()));
if (LookupCtx)
Diag(Found.getNameLoc(), diag::err_no_member_suggest)
<< Name << LookupCtx << Found.getLookupName() << SS.getRange()
<< FixItHint::CreateReplacement(Found.getNameLoc(),
Found.getLookupName().getAsString());
<< Name << LookupCtx << CorrectedQuotedStr << SS.getRange()
<< FixItHint::CreateReplacement(Found.getNameLoc(), CorrectedStr);
else
Diag(Found.getNameLoc(), diag::err_undeclared_var_use_suggest)
<< Name << Found.getLookupName()
<< FixItHint::CreateReplacement(Found.getNameLoc(),
Found.getLookupName().getAsString());
<< Name << CorrectedQuotedStr
<< FixItHint::CreateReplacement(Found.getNameLoc(), CorrectedStr);
if (NamedDecl *ND = Found.getAsSingle<NamedDecl>())
Diag(ND->getLocation(), diag::note_previous_decl)
<< ND->getDeclName();
if (NamedDecl *ND = Corrected.getCorrectionDecl()) {
Diag(ND->getLocation(), diag::note_previous_decl) << CorrectedQuotedStr;
Found.addDecl(ND);
}
Found.setLookupName(Corrected.getCorrection());
} else {
Found.clear();
Found.setLookupName(&Identifier);
}
}

View File

@ -287,41 +287,42 @@ bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II,
// There may have been a typo in the name of the type. Look up typo
// results, in case we have something that we can suggest.
LookupResult Lookup(*this, &II, IILoc, LookupOrdinaryName,
NotForRedeclaration);
if (TypoCorrection Corrected = CorrectTypo(DeclarationNameInfo(&II, IILoc),
LookupOrdinaryName, S, SS, NULL,
false, CTC_Type)) {
std::string CorrectedStr(Corrected.getAsString(getLangOptions()));
std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOptions()));
if (DeclarationName Corrected = CorrectTypo(Lookup, S, SS, 0, 0, CTC_Type)) {
if (NamedDecl *Result = Lookup.getAsSingle<NamedDecl>()) {
if (Corrected.isKeyword()) {
// We corrected to a keyword.
// FIXME: Actually recover with the keyword we suggest, and emit a fix-it.
Diag(IILoc, diag::err_unknown_typename_suggest)
<< &II << CorrectedQuotedStr;
return true;
} else {
NamedDecl *Result = Corrected.getCorrectionDecl();
if ((isa<TypeDecl>(Result) || isa<ObjCInterfaceDecl>(Result)) &&
!Result->isInvalidDecl()) {
// We found a similarly-named type or interface; suggest that.
if (!SS || !SS->isSet())
Diag(IILoc, diag::err_unknown_typename_suggest)
<< &II << Lookup.getLookupName()
<< FixItHint::CreateReplacement(SourceRange(IILoc),
Result->getNameAsString());
<< &II << CorrectedQuotedStr
<< FixItHint::CreateReplacement(SourceRange(IILoc), CorrectedStr);
else if (DeclContext *DC = computeDeclContext(*SS, false))
Diag(IILoc, diag::err_unknown_nested_typename_suggest)
<< &II << DC << Lookup.getLookupName() << SS->getRange()
<< FixItHint::CreateReplacement(SourceRange(IILoc),
Result->getNameAsString());
<< &II << DC << CorrectedQuotedStr << SS->getRange()
<< FixItHint::CreateReplacement(SourceRange(IILoc), CorrectedStr);
else
llvm_unreachable("could not have corrected a typo here");
Diag(Result->getLocation(), diag::note_previous_decl)
<< Result->getDeclName();
<< CorrectedQuotedStr;
SuggestedType = getTypeName(*Result->getIdentifier(), IILoc, S, SS,
false, false, ParsedType(),
/*NonTrivialTypeSourceInfo=*/true);
return true;
}
} else if (Lookup.empty()) {
// We corrected to a keyword.
// FIXME: Actually recover with the keyword we suggest, and emit a fix-it.
Diag(IILoc, diag::err_unknown_typename_suggest)
<< &II << Corrected;
return true;
}
}
@ -509,11 +510,14 @@ Corrected:
// Perform typo correction to determine if there is another name that is
// close to this name.
if (!SecondTry) {
if (DeclarationName Corrected = CorrectTypo(Result, S, &SS)) {
if (TypoCorrection Corrected = CorrectTypo(Result.getLookupNameInfo(),
Result.getLookupKind(), S, &SS)) {
unsigned UnqualifiedDiag = diag::err_undeclared_var_use_suggest;
unsigned QualifiedDiag = diag::err_no_member_suggest;
std::string CorrectedStr(Corrected.getAsString(getLangOptions()));
std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOptions()));
NamedDecl *FirstDecl = Result.empty()? 0 : *Result.begin();
NamedDecl *FirstDecl = Corrected.getCorrectionDecl();
NamedDecl *UnderlyingFirstDecl
= FirstDecl? FirstDecl->getUnderlyingDecl() : 0;
if (getLangOptions().CPlusPlus && NextToken.is(tok::less) &&
@ -528,25 +532,34 @@ Corrected:
QualifiedDiag = diag::err_unknown_nested_typename_suggest;
}
if (Corrected.getCorrectionSpecifier())
SS.MakeTrivial(Context, Corrected.getCorrectionSpecifier(), SourceRange(NameLoc));
if (SS.isEmpty())
Diag(NameLoc, UnqualifiedDiag)
<< Name << Corrected
<< FixItHint::CreateReplacement(NameLoc, Corrected.getAsString());
<< Name << CorrectedQuotedStr
<< FixItHint::CreateReplacement(NameLoc, CorrectedStr);
else
Diag(NameLoc, QualifiedDiag)
<< Name << computeDeclContext(SS, false) << Corrected
<< Name << computeDeclContext(SS, false) << CorrectedQuotedStr
<< SS.getRange()
<< FixItHint::CreateReplacement(NameLoc, Corrected.getAsString());
<< FixItHint::CreateReplacement(NameLoc, CorrectedStr);
// Update the name, so that the caller has the new name.
Name = Corrected.getAsIdentifierInfo();
Name = Corrected.getCorrectionAsIdentifierInfo();
// Also update the LookupResult...
// FIXME: This should probably go away at some point
Result.clear();
Result.setLookupName(Corrected.getCorrection());
if (FirstDecl) Result.addDecl(FirstDecl);
// Typo correction corrected to a keyword.
if (Result.empty())
return Corrected.getAsIdentifierInfo();
if (Corrected.isKeyword())
return Corrected.getCorrectionAsIdentifierInfo();
Diag(FirstDecl->getLocation(), diag::note_previous_decl)
<< FirstDecl->getDeclName();
<< CorrectedQuotedStr;
// If we found an Objective-C instance variable, let
// LookupInObjCMethod build the appropriate expression to
@ -1137,17 +1150,18 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
/// class could not be found.
ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *&Id,
SourceLocation IdLoc,
bool TypoCorrection) {
bool DoTypoCorrection) {
// The third "scope" argument is 0 since we aren't enabling lazy built-in
// creation from this context.
NamedDecl *IDecl = LookupSingleName(TUScope, Id, IdLoc, LookupOrdinaryName);
if (!IDecl && TypoCorrection) {
if (!IDecl && DoTypoCorrection) {
// Perform typo correction at the given location, but only if we
// find an Objective-C class name.
LookupResult R(*this, Id, IdLoc, LookupOrdinaryName);
if (CorrectTypo(R, TUScope, 0, 0, false, CTC_NoKeywords) &&
(IDecl = R.getAsSingle<ObjCInterfaceDecl>())) {
TypoCorrection C;
if ((C = CorrectTypo(DeclarationNameInfo(Id, IdLoc), LookupOrdinaryName,
TUScope, NULL, NULL, false, CTC_NoKeywords)) &&
(IDecl = C.getCorrectionDeclAs<ObjCInterfaceDecl>())) {
Diag(IdLoc, diag::err_undef_interface_suggest)
<< Id << IDecl->getDeclName()
<< FixItHint::CreateReplacement(IdLoc, IDecl->getNameAsString());

View File

@ -1426,25 +1426,27 @@ Sema::ActOnMemInitializer(Decl *ConstructorD,
}
// If no results were found, try to correct typos.
TypoCorrection Corr;
if (R.empty() && BaseType.isNull() &&
CorrectTypo(R, S, &SS, ClassDecl, 0, CTC_NoKeywords) &&
R.isSingleResult()) {
if (FieldDecl *Member = R.getAsSingle<FieldDecl>()) {
(Corr = CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), S, &SS,
ClassDecl, false, CTC_NoKeywords))) {
std::string CorrectedStr(Corr.getAsString(getLangOptions()));
std::string CorrectedQuotedStr(Corr.getQuoted(getLangOptions()));
if (FieldDecl *Member = Corr.getCorrectionDeclAs<FieldDecl>()) {
if (Member->getDeclContext()->getRedeclContext()->Equals(ClassDecl)) {
// We have found a non-static data member with a similar
// name to what was typed; complain and initialize that
// member.
Diag(R.getNameLoc(), diag::err_mem_init_not_member_or_class_suggest)
<< MemberOrBase << true << R.getLookupName()
<< FixItHint::CreateReplacement(R.getNameLoc(),
R.getLookupName().getAsString());
<< MemberOrBase << true << CorrectedQuotedStr
<< FixItHint::CreateReplacement(R.getNameLoc(), CorrectedStr);
Diag(Member->getLocation(), diag::note_previous_decl)
<< Member->getDeclName();
<< CorrectedQuotedStr;
return BuildMemberInitializer(Member, (Expr**)Args, NumArgs, IdLoc,
LParenLoc, RParenLoc);
}
} else if (TypeDecl *Type = R.getAsSingle<TypeDecl>()) {
} else if (TypeDecl *Type = Corr.getCorrectionDeclAs<TypeDecl>()) {
const CXXBaseSpecifier *DirectBaseSpec;
const CXXBaseSpecifier *VirtualBaseSpec;
if (FindBaseInitializer(*this, ClassDecl,
@ -1454,9 +1456,8 @@ Sema::ActOnMemInitializer(Decl *ConstructorD,
// similar name to what was typed; complain and initialize
// that base class.
Diag(R.getNameLoc(), diag::err_mem_init_not_member_or_class_suggest)
<< MemberOrBase << false << R.getLookupName()
<< FixItHint::CreateReplacement(R.getNameLoc(),
R.getLookupName().getAsString());
<< MemberOrBase << false << CorrectedQuotedStr
<< FixItHint::CreateReplacement(R.getNameLoc(), CorrectedStr);
const CXXBaseSpecifier *BaseSpec = DirectBaseSpec? DirectBaseSpec
: VirtualBaseSpec;
@ -4706,6 +4707,13 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
// Make our StdNamespace cache point at the first real definition of the
// "std" namespace.
StdNamespace = Namespc;
// Add this instance of "std" to the set of known namespaces
KnownNamespaces[Namespc] = false;
} else if (!Namespc->isInline()) {
// Since this is an "original" namespace, add it to the known set of
// namespaces if it is not an inline namespace.
KnownNamespaces[Namespc] = false;
}
PushOnScopeChains(Namespc, DeclRegionScope);
@ -4841,6 +4849,39 @@ static bool IsUsingDirectiveInToplevelContext(DeclContext *CurContext) {
}
}
static bool TryNamespaceTypoCorrection(Sema &S, LookupResult &R, Scope *Sc,
CXXScopeSpec &SS,
SourceLocation IdentLoc,
IdentifierInfo *Ident) {
R.clear();
if (TypoCorrection Corrected = S.CorrectTypo(R.getLookupNameInfo(),
R.getLookupKind(), Sc, &SS, NULL,
false, S.CTC_NoKeywords, NULL)) {
if (Corrected.getCorrectionDeclAs<NamespaceDecl>() ||
Corrected.getCorrectionDeclAs<NamespaceAliasDecl>()) {
std::string CorrectedStr(Corrected.getAsString(S.getLangOptions()));
std::string CorrectedQuotedStr(Corrected.getQuoted(S.getLangOptions()));
if (DeclContext *DC = S.computeDeclContext(SS, false))
S.Diag(IdentLoc, diag::err_using_directive_member_suggest)
<< Ident << DC << CorrectedQuotedStr << SS.getRange()
<< FixItHint::CreateReplacement(IdentLoc, CorrectedStr);
else
S.Diag(IdentLoc, diag::err_using_directive_suggest)
<< Ident << CorrectedQuotedStr
<< FixItHint::CreateReplacement(IdentLoc, CorrectedStr);
S.Diag(Corrected.getCorrectionDecl()->getLocation(),
diag::note_namespace_defined_here) << CorrectedQuotedStr;
Ident = Corrected.getCorrectionAsIdentifierInfo();
R.addDecl(Corrected.getCorrectionDecl());
return true;
}
R.setLookupName(Ident);
}
return false;
}
Decl *Sema::ActOnUsingDirective(Scope *S,
SourceLocation UsingLoc,
SourceLocation NamespcLoc,
@ -4869,6 +4910,7 @@ Decl *Sema::ActOnUsingDirective(Scope *S,
return 0;
if (R.empty()) {
R.clear();
// Allow "using namespace std;" or "using namespace ::std;" even if
// "std" hasn't been defined yet, for GCC compatibility.
if ((!Qualifier || Qualifier->getKind() == NestedNameSpecifier::Global) &&
@ -4878,27 +4920,7 @@ Decl *Sema::ActOnUsingDirective(Scope *S,
R.resolveKind();
}
// Otherwise, attempt typo correction.
else if (DeclarationName Corrected = CorrectTypo(R, S, &SS, 0, false,
CTC_NoKeywords, 0)) {
if (R.getAsSingle<NamespaceDecl>() ||
R.getAsSingle<NamespaceAliasDecl>()) {
if (DeclContext *DC = computeDeclContext(SS, false))
Diag(IdentLoc, diag::err_using_directive_member_suggest)
<< NamespcName << DC << Corrected << SS.getRange()
<< FixItHint::CreateReplacement(IdentLoc, Corrected.getAsString());
else
Diag(IdentLoc, diag::err_using_directive_suggest)
<< NamespcName << Corrected
<< FixItHint::CreateReplacement(IdentLoc, Corrected.getAsString());
Diag(R.getFoundDecl()->getLocation(), diag::note_namespace_defined_here)
<< Corrected;
NamespcName = Corrected.getAsIdentifierInfo();
} else {
R.clear();
R.setLookupName(NamespcName);
}
}
else TryNamespaceTypoCorrection(*this, R, S, SS, IdentLoc, NamespcName);
}
if (!R.empty()) {
@ -5816,30 +5838,7 @@ Decl *Sema::ActOnNamespaceAliasDef(Scope *S,
return 0;
if (R.empty()) {
if (DeclarationName Corrected = CorrectTypo(R, S, &SS, 0, false,
CTC_NoKeywords, 0)) {
if (R.getAsSingle<NamespaceDecl>() ||
R.getAsSingle<NamespaceAliasDecl>()) {
if (DeclContext *DC = computeDeclContext(SS, false))
Diag(IdentLoc, diag::err_using_directive_member_suggest)
<< Ident << DC << Corrected << SS.getRange()
<< FixItHint::CreateReplacement(IdentLoc, Corrected.getAsString());
else
Diag(IdentLoc, diag::err_using_directive_suggest)
<< Ident << Corrected
<< FixItHint::CreateReplacement(IdentLoc, Corrected.getAsString());
Diag(R.getFoundDecl()->getLocation(), diag::note_namespace_defined_here)
<< Corrected;
Ident = Corrected.getAsIdentifierInfo();
} else {
R.clear();
R.setLookupName(Ident);
}
}
if (R.empty()) {
if (!TryNamespaceTypoCorrection(*this, R, S, SS, IdentLoc, Ident)) {
Diag(NamespaceLoc, diag::err_expected_namespace_name) << SS.getRange();
return 0;
}

View File

@ -442,9 +442,10 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
if (!PrevDecl) {
// Try to correct for a typo in the superclass name.
LookupResult R(*this, SuperName, SuperLoc, LookupOrdinaryName);
if (CorrectTypo(R, TUScope, 0, 0, false, CTC_NoKeywords) &&
(PrevDecl = R.getAsSingle<ObjCInterfaceDecl>())) {
TypoCorrection Corrected = CorrectTypo(
DeclarationNameInfo(SuperName, SuperLoc), LookupOrdinaryName, TUScope,
NULL, NULL, false, CTC_NoKeywords);
if ((PrevDecl = Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>())) {
Diag(SuperLoc, diag::err_undef_superclass_suggest)
<< SuperName << ClassName << PrevDecl->getDeclName();
Diag(PrevDecl->getLocation(), diag::note_previous_decl)
@ -655,12 +656,12 @@ Sema::FindProtocolDeclaration(bool WarnOnDeclarations,
ObjCProtocolDecl *PDecl = LookupProtocol(ProtocolId[i].first,
ProtocolId[i].second);
if (!PDecl) {
LookupResult R(*this, ProtocolId[i].first, ProtocolId[i].second,
LookupObjCProtocolName);
if (CorrectTypo(R, TUScope, 0, 0, false, CTC_NoKeywords) &&
(PDecl = R.getAsSingle<ObjCProtocolDecl>())) {
TypoCorrection Corrected = CorrectTypo(
DeclarationNameInfo(ProtocolId[i].first, ProtocolId[i].second),
LookupObjCProtocolName, TUScope, NULL, NULL, false, CTC_NoKeywords);
if ((PDecl = Corrected.getCorrectionDeclAs<ObjCProtocolDecl>())) {
Diag(ProtocolId[i].second, diag::err_undeclared_protocol_suggest)
<< ProtocolId[i].first << R.getLookupName();
<< ProtocolId[i].first << Corrected.getCorrection();
Diag(PDecl->getLocation(), diag::note_previous_decl)
<< PDecl->getDeclName();
}
@ -897,20 +898,20 @@ Decl *Sema::ActOnStartClassImplementation(
} else {
// We did not find anything with the name ClassName; try to correct for
// typos in the class name.
LookupResult R(*this, ClassName, ClassLoc, LookupOrdinaryName);
if (CorrectTypo(R, TUScope, 0, 0, false, CTC_NoKeywords) &&
(IDecl = R.getAsSingle<ObjCInterfaceDecl>())) {
TypoCorrection Corrected = CorrectTypo(
DeclarationNameInfo(ClassName, ClassLoc), LookupOrdinaryName, TUScope,
NULL, NULL, false, CTC_NoKeywords);
if ((IDecl = Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>())) {
// Suggest the (potentially) correct interface name. However, put the
// fix-it hint itself in a separate note, since changing the name in
// the warning would make the fix-it change semantics.However, don't
// provide a code-modification hint or use the typo name for recovery,
// because this is just a warning. The program may actually be correct.
DeclarationName CorrectedName = Corrected.getCorrection();
Diag(ClassLoc, diag::warn_undef_interface_suggest)
<< ClassName << R.getLookupName();
Diag(IDecl->getLocation(), diag::note_previous_decl)
<< R.getLookupName()
<< FixItHint::CreateReplacement(ClassLoc,
R.getLookupName().getAsString());
<< ClassName << CorrectedName;
Diag(IDecl->getLocation(), diag::note_previous_decl) << CorrectedName
<< FixItHint::CreateReplacement(ClassLoc, CorrectedName.getAsString());
IDecl = 0;
} else {
Diag(ClassLoc, diag::warn_undef_interface) << ClassName;

View File

@ -1397,39 +1397,44 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
}
// We didn't find anything, so try to correct for a typo.
DeclarationName Corrected;
if (S && (Corrected = CorrectTypo(R, S, &SS, 0, false, CTC))) {
if (!R.empty()) {
if (isa<ValueDecl>(*R.begin()) || isa<FunctionTemplateDecl>(*R.begin())) {
TypoCorrection Corrected;
if (S && (Corrected = CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(),
S, &SS, NULL, false, CTC))) {
std::string CorrectedStr(Corrected.getAsString(getLangOptions()));
std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOptions()));
R.setLookupName(Corrected.getCorrection());
if (!Corrected.isKeyword()) {
NamedDecl *ND = Corrected.getCorrectionDecl();
R.addDecl(ND);
if (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND)) {
if (SS.isEmpty())
Diag(R.getNameLoc(), diagnostic_suggest) << Name << R.getLookupName()
<< FixItHint::CreateReplacement(R.getNameLoc(),
R.getLookupName().getAsString());
Diag(R.getNameLoc(), diagnostic_suggest) << Name << CorrectedQuotedStr
<< FixItHint::CreateReplacement(R.getNameLoc(), CorrectedStr);
else
Diag(R.getNameLoc(), diag::err_no_member_suggest)
<< Name << computeDeclContext(SS, false) << R.getLookupName()
<< Name << computeDeclContext(SS, false) << CorrectedQuotedStr
<< SS.getRange()
<< FixItHint::CreateReplacement(R.getNameLoc(),
R.getLookupName().getAsString());
if (NamedDecl *ND = R.getAsSingle<NamedDecl>())
<< FixItHint::CreateReplacement(R.getNameLoc(), CorrectedStr);
if (ND)
Diag(ND->getLocation(), diag::note_previous_decl)
<< ND->getDeclName();
<< CorrectedQuotedStr;
// Tell the callee to try to recover.
return false;
}
if (isa<TypeDecl>(*R.begin()) || isa<ObjCInterfaceDecl>(*R.begin())) {
if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) {
// FIXME: If we ended up with a typo for a type name or
// Objective-C class name, we're in trouble because the parser
// is in the wrong place to recover. Suggest the typo
// correction, but don't make it a fix-it since we're not going
// to recover well anyway.
if (SS.isEmpty())
Diag(R.getNameLoc(), diagnostic_suggest) << Name << R.getLookupName();
Diag(R.getNameLoc(), diagnostic_suggest) << Name << CorrectedQuotedStr;
else
Diag(R.getNameLoc(), diag::err_no_member_suggest)
<< Name << computeDeclContext(SS, false) << R.getLookupName()
<< Name << computeDeclContext(SS, false) << CorrectedQuotedStr
<< SS.getRange();
// Don't try to recover; it won't work.
@ -1439,15 +1444,15 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
// FIXME: We found a keyword. Suggest it, but don't provide a fix-it
// because we aren't able to recover.
if (SS.isEmpty())
Diag(R.getNameLoc(), diagnostic_suggest) << Name << Corrected;
Diag(R.getNameLoc(), diagnostic_suggest) << Name << CorrectedQuotedStr;
else
Diag(R.getNameLoc(), diag::err_no_member_suggest)
<< Name << computeDeclContext(SS, false) << Corrected
<< Name << computeDeclContext(SS, false) << CorrectedQuotedStr
<< SS.getRange();
return true;
}
R.clear();
}
R.clear();
// Emit a special diagnostic for failed member lookups.
// FIXME: computing the declaration context might fail here (?)

View File

@ -555,20 +555,24 @@ LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
// We didn't find anything with the given name, so try to correct
// for typos.
DeclarationName Name = R.getLookupName();
if (SemaRef.CorrectTypo(R, 0, &SS, DC, false, Sema::CTC_MemberLookup) &&
!R.empty() &&
(isa<ValueDecl>(*R.begin()) || isa<FunctionTemplateDecl>(*R.begin()))) {
TypoCorrection Corrected = SemaRef.CorrectTypo(R.getLookupNameInfo(),
R.getLookupKind(), NULL,
&SS, DC, false,
Sema::CTC_MemberLookup);
NamedDecl *ND = Corrected.getCorrectionDecl();
R.clear();
if (ND && (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND))) {
std::string CorrectedStr(
Corrected.getAsString(SemaRef.getLangOptions()));
std::string CorrectedQuotedStr(
Corrected.getQuoted(SemaRef.getLangOptions()));
R.setLookupName(Corrected.getCorrection());
R.addDecl(ND);
SemaRef.Diag(R.getNameLoc(), diag::err_no_member_suggest)
<< Name << DC << R.getLookupName() << SS.getRange()
<< FixItHint::CreateReplacement(R.getNameLoc(),
R.getLookupName().getAsString());
if (NamedDecl *ND = R.getAsSingle<NamedDecl>())
SemaRef.Diag(ND->getLocation(), diag::note_previous_decl)
<< ND->getDeclName();
return false;
} else {
R.clear();
R.setLookupName(Name);
<< Name << DC << CorrectedQuotedStr << SS.getRange()
<< FixItHint::CreateReplacement(R.getNameLoc(), CorrectedStr);
SemaRef.Diag(ND->getLocation(), diag::note_previous_decl)
<< ND->getDeclName();
}
return false;
@ -1068,10 +1072,10 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr,
// Attempt to correct for typos in ivar names.
LookupResult Res(*this, R.getLookupName(), R.getNameLoc(),
LookupMemberName);
if (CorrectTypo(Res, 0, 0, IDecl, false,
IsArrow ? CTC_ObjCIvarLookup
: CTC_ObjCPropertyLookup) &&
(IV = Res.getAsSingle<ObjCIvarDecl>())) {
TypoCorrection Corrected = CorrectTypo(
R.getLookupNameInfo(), LookupMemberName, NULL, NULL, IDecl, false,
IsArrow ? CTC_ObjCIvarLookup : CTC_ObjCPropertyLookup);
if ((IV = Corrected.getCorrectionDeclAs<ObjCIvarDecl>())) {
Diag(R.getNameLoc(),
diag::err_typecheck_member_reference_ivar_suggest)
<< IDecl->getDeclName() << MemberName << IV->getDeclName()

View File

@ -663,14 +663,15 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
}
// Attempt to correct for typos in property names.
LookupResult Res(*this, MemberName, MemberLoc, LookupOrdinaryName);
if (CorrectTypo(Res, 0, 0, IFace, false, CTC_NoKeywords, OPT) &&
Res.getAsSingle<ObjCPropertyDecl>()) {
DeclarationName TypoResult = Res.getLookupName();
TypoCorrection Corrected = CorrectTypo(
DeclarationNameInfo(MemberName, MemberLoc), LookupOrdinaryName, NULL,
NULL, IFace, false, CTC_NoKeywords, OPT);
if (ObjCPropertyDecl *Property =
Corrected.getCorrectionDeclAs<ObjCPropertyDecl>()) {
DeclarationName TypoResult = Corrected.getCorrection();
Diag(MemberLoc, diag::err_property_not_found_suggest)
<< MemberName << QualType(OPT, 0) << TypoResult
<< FixItHint::CreateReplacement(MemberLoc, TypoResult.getAsString());
ObjCPropertyDecl *Property = Res.getAsSingle<ObjCPropertyDecl>();
Diag(Property->getLocation(), diag::note_previous_decl)
<< Property->getDeclName();
return HandleExprPropertyRefExpr(OPT, BaseExpr, OpLoc,
@ -898,29 +899,30 @@ Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S,
Method->getClassInterface()->getSuperClass())
CTC = CTC_ObjCMessageReceiver;
if (DeclarationName Corrected = CorrectTypo(Result, S, 0, 0, false, CTC)) {
if (Result.isSingleResult()) {
if (TypoCorrection Corrected = CorrectTypo(Result.getLookupNameInfo(),
Result.getLookupKind(), S, NULL,
NULL, false, CTC)) {
if (NamedDecl *ND = Corrected.getCorrectionDecl()) {
// If we found a declaration, correct when it refers to an Objective-C
// class.
NamedDecl *ND = Result.getFoundDecl();
if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(ND)) {
Diag(NameLoc, diag::err_unknown_receiver_suggest)
<< Name << Result.getLookupName()
<< Name << Corrected.getCorrection()
<< FixItHint::CreateReplacement(SourceRange(NameLoc),
ND->getNameAsString());
Diag(ND->getLocation(), diag::note_previous_decl)
<< Corrected;
<< Corrected.getCorrection();
QualType T = Context.getObjCInterfaceType(Class);
TypeSourceInfo *TSInfo = Context.getTrivialTypeSourceInfo(T, NameLoc);
ReceiverType = CreateParsedType(T, TSInfo);
return ObjCClassMessage;
}
} else if (Result.empty() && Corrected.getAsIdentifierInfo() &&
Corrected.getAsIdentifierInfo()->isStr("super")) {
} else if (Corrected.isKeyword() &&
Corrected.getCorrectionAsIdentifierInfo()->isStr("super")) {
// If we've found the keyword "super", this is a send to super.
Diag(NameLoc, diag::err_unknown_receiver_suggest)
<< Name << Corrected
<< Name << Corrected.getCorrection()
<< FixItHint::CreateReplacement(SourceRange(NameLoc), "super");
return ObjCSuperMessage;
}

View File

@ -1443,19 +1443,23 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
// was a typo for another field name.
LookupResult R(SemaRef, FieldName, D->getFieldLoc(),
Sema::LookupMemberName);
if (SemaRef.CorrectTypo(R, /*Scope=*/0, /*SS=*/0, RT->getDecl(), false,
Sema::CTC_NoKeywords) &&
(ReplacementField = R.getAsSingle<FieldDecl>()) &&
TypoCorrection Corrected = SemaRef.CorrectTypo(
DeclarationNameInfo(FieldName, D->getFieldLoc()),
Sema::LookupMemberName, /*Scope=*/NULL, /*SS=*/NULL,
RT->getDecl(), false, Sema::CTC_NoKeywords);
if ((ReplacementField = Corrected.getCorrectionDeclAs<FieldDecl>()) &&
ReplacementField->getDeclContext()->getRedeclContext()
->Equals(RT->getDecl())) {
std::string CorrectedStr(
Corrected.getAsString(SemaRef.getLangOptions()));
std::string CorrectedQuotedStr(
Corrected.getQuoted(SemaRef.getLangOptions()));
SemaRef.Diag(D->getFieldLoc(),
diag::err_field_designator_unknown_suggest)
<< FieldName << CurrentObjectType << R.getLookupName()
<< FixItHint::CreateReplacement(D->getFieldLoc(),
R.getLookupName().getAsString());
<< FieldName << CurrentObjectType << CorrectedQuotedStr
<< FixItHint::CreateReplacement(D->getFieldLoc(), CorrectedStr);
SemaRef.Diag(ReplacementField->getLocation(),
diag::note_previous_decl)
<< ReplacementField->getDeclName();
diag::note_previous_decl) << CorrectedQuotedStr;
} else {
SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_unknown)
<< FieldName << CurrentObjectType;

File diff suppressed because it is too large Load Diff

View File

@ -294,26 +294,31 @@ void Sema::LookupTemplateName(LookupResult &Found,
if (Found.empty() && !isDependent) {
// If we did not find any names, attempt to correct any typos.
DeclarationName Name = Found.getLookupName();
if (DeclarationName Corrected = CorrectTypo(Found, S, &SS, LookupCtx,
false, CTC_CXXCasts)) {
Found.clear();
if (TypoCorrection Corrected = CorrectTypo(Found.getLookupNameInfo(),
Found.getLookupKind(), S, &SS,
LookupCtx, false,
CTC_CXXCasts)) {
Found.setLookupName(Corrected.getCorrection());
if (Corrected.getCorrectionDecl())
Found.addDecl(Corrected.getCorrectionDecl());
FilterAcceptableTemplateNames(Found);
if (!Found.empty()) {
std::string CorrectedStr(Corrected.getAsString(getLangOptions()));
std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOptions()));
if (LookupCtx)
Diag(Found.getNameLoc(), diag::err_no_member_template_suggest)
<< Name << LookupCtx << Found.getLookupName() << SS.getRange()
<< FixItHint::CreateReplacement(Found.getNameLoc(),
Found.getLookupName().getAsString());
<< Name << LookupCtx << CorrectedQuotedStr << SS.getRange()
<< FixItHint::CreateReplacement(Found.getNameLoc(), CorrectedStr);
else
Diag(Found.getNameLoc(), diag::err_no_template_suggest)
<< Name << Found.getLookupName()
<< FixItHint::CreateReplacement(Found.getNameLoc(),
Found.getLookupName().getAsString());
<< Name << CorrectedQuotedStr
<< FixItHint::CreateReplacement(Found.getNameLoc(), CorrectedStr);
if (TemplateDecl *Template = Found.getAsSingle<TemplateDecl>())
Diag(Template->getLocation(), diag::note_previous_decl)
<< Template->getDeclName();
<< CorrectedQuotedStr;
}
} else {
Found.clear();
Found.setLookupName(Name);
}
}

View File

@ -716,17 +716,19 @@ ExprResult Sema::ActOnSizeofParameterPackExpr(Scope *S,
case LookupResult::NotFound:
case LookupResult::NotFoundInCurrentInstantiation:
if (DeclarationName CorrectedName = CorrectTypo(R, S, 0, 0, false,
CTC_NoKeywords)) {
if (NamedDecl *CorrectedResult = R.getAsSingle<NamedDecl>())
if (TypoCorrection Corrected = CorrectTypo(R.getLookupNameInfo(),
R.getLookupKind(), S, 0, 0,
false, CTC_NoKeywords)) {
if (NamedDecl *CorrectedResult = Corrected.getCorrectionDecl())
if (CorrectedResult->isParameterPack()) {
std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOptions()));
ParameterPack = CorrectedResult;
Diag(NameLoc, diag::err_sizeof_pack_no_pack_name_suggest)
<< &Name << CorrectedName
<< FixItHint::CreateReplacement(NameLoc,
CorrectedName.getAsString());
<< &Name << CorrectedQuotedStr
<< FixItHint::CreateReplacement(
NameLoc, Corrected.getAsString(getLangOptions()));
Diag(ParameterPack->getLocation(), diag::note_parameter_pack_here)
<< CorrectedName;
<< CorrectedQuotedStr;
}
}

View File

@ -2369,6 +2369,15 @@ ASTReader::ReadASTBlock(PerFileData &F) {
TentativeDefinitions.insert(TentativeDefinitions.end(),
Record.begin(), Record.end());
break;
case KNOWN_NAMESPACES:
// Optimization for the first block.
if (KnownNamespaces.empty())
KnownNamespaces.swap(Record);
else
KnownNamespaces.insert(KnownNamespaces.end(),
Record.begin(), Record.end());
break;
}
First = false;
}
@ -4452,6 +4461,17 @@ ASTReader::ReadMethodPool(Selector Sel) {
return std::pair<ObjCMethodList, ObjCMethodList>();
}
void ASTReader::ReadKnownNamespaces(
llvm::SmallVectorImpl<NamespaceDecl *> &Namespaces) {
Namespaces.clear();
for (unsigned I = 0, N = KnownNamespaces.size(); I != N; ++I) {
if (NamespaceDecl *Namespace
= dyn_cast_or_null<NamespaceDecl>(GetDecl(KnownNamespaces[I])))
Namespaces.push_back(Namespace);
}
}
void ASTReader::LoadSelector(Selector Sel) {
// It would be complicated to avoid reading the methods anyway. So don't.
ReadMethodPool(Sel);

View File

@ -781,6 +781,8 @@ void ASTWriter::WriteBlockInfoBlock() {
RECORD(FP_PRAGMA_OPTIONS);
RECORD(OPENCL_EXTENSIONS);
RECORD(DELEGATING_CTORS);
RECORD(FILE_SOURCE_LOCATION_OFFSETS);
RECORD(KNOWN_NAMESPACES);
// SourceManager Block.
BLOCK(SOURCE_MANAGER_BLOCK);
@ -2845,6 +2847,16 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls,
AddDeclRef(Context.getcudaConfigureCallDecl(), CUDASpecialDeclRefs);
}
// Build a record containing all of the known namespaces.
RecordData KnownNamespaces;
for (llvm::DenseMap<NamespaceDecl*, bool>::iterator
I = SemaRef.KnownNamespaces.begin(),
IEnd = SemaRef.KnownNamespaces.end();
I != IEnd; ++I) {
if (!I->second)
AddDeclRef(I->first, KnownNamespaces);
}
// Write the remaining AST contents.
RecordData Record;
Stream.EnterSubblock(AST_BLOCK_ID, 5);
@ -2954,6 +2966,10 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls,
if (!DelegatingCtorDecls.empty())
Stream.EmitRecord(DELEGATING_CTORS, DelegatingCtorDecls);
// Write the known namespaces.
if (!KnownNamespaces.empty())
Stream.EmitRecord(KNOWN_NAMESPACES, KnownNamespaces);
// Some simple statistics
Record.clear();
Record.push_back(NumStatements);

View File

@ -19,8 +19,9 @@ namespace D {
}
namespace C {
class C {};
void func(C);
class C {}; // expected-note {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'B::B' to 'const C::C &' for 1st argument}}
void func(C); // expected-note {{'C::func' declared here}} \
// expected-note {{passing argument to parameter here}}
C operator+(C,C);
D::D operator+(D::D,D::D);
}
@ -32,7 +33,13 @@ namespace D {
namespace Test {
void test() {
func(A::A());
func(B::B()); // expected-error {{use of undeclared identifier 'func'}}
// FIXME: namespace-aware typo correction causes an extra, misleading
// message in this case; some form of backtracking, diagnostic message
// delaying, or argument checking before emitting diagnostics is needed to
// avoid accepting and printing out a typo correction that proves to be
// incorrect once argument-dependent lookup resolution has occurred.
func(B::B()); // expected-error {{use of undeclared identifier 'func'; did you mean 'C::func'?}} \
// expected-error {{no viable conversion from 'B::B' to 'C::C'}}
func(C::C());
A::A() + A::A();
B::B() + B::B();

View File

@ -74,3 +74,9 @@ int foo() {
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'?}}
}
namespace nonstd {
typedef std::basic_string<char> yarn; // expected-note{{'nonstd::yarn' declared here}}
}
yarn str4; // expected-error{{unknown type name 'yarn'; did you mean 'nonstd::yarn'?}}

View File

@ -0,0 +1,8 @@
namespace boost {
template<typename F> class function {};
namespace graph {
template<typename V, typename E> class adjacency_list { };
};
}

17
clang/test/PCH/typo.cpp Normal file
View File

@ -0,0 +1,17 @@
// In header: expected-note{{ 'boost::function' declared here}}
// In header: expected-note{{ 'boost::graph::adjacency_list' declared here}}
adjacent_list<int, int> g; // expected-error{{no template named 'adjacent_list'; did you mean 'boost::graph::adjacency_list'?}}
Function<int(int)> f; // expected-error{{no template named 'Function'; did you mean 'boost::function'?}}
// Without PCH
// RUN: %clang_cc1 -include %S/Inputs/typo.hpp -verify %s
// With PCH
// RUN: %clang_cc1 -x c++-header -emit-pch -o %t %S/Inputs/typo.hpp
// RUN: %clang_cc1 -include-pch %t -verify %s

View File

@ -0,0 +1,61 @@
// RUN: %clang_cc1 -fsyntax-only -verify -Wno-c++0x-extensions %s
namespace fizbin { class Foobar; } // expected-note{{'fizbin::Foobar' declared here}}
Foobar *my_bar = new Foobar; // expected-error{{unknown type name 'Foobar'; did you mean 'fizbin::Foobar'?}} \
// expected-error{{expected a type}}
namespace barstool { int toFoobar() { return 1; } } // expected-note 3 {{'barstool::toFoobar' declared here}}
int Double(int x) { return x + x; }
void empty() {
Double(toFoobar()); // expected-error{{{use of undeclared identifier 'toFoobar'; did you mean 'barstool::toFoobar'?}}
}
namespace fizbin {
namespace baztool { bool toFoobar() { return true; } } // expected-note{{'fizbin::baztool' declared here}}
namespace nested { bool moreFoobar() { return true; } } // expected-note{{'fizbin::nested::moreFoobar' declared here}}
namespace nested { bool lessFoobar() { return true; } } // expected-note{{'fizbin::nested' declared here}} \
// expected-note{{'fizbin::nested::lessFoobar' declared here}}
class dummy { // expected-note 2 {{'fizbin::dummy' declared here}}
public:
static bool moreFoobar() { return false; } // expected-note{{'moreFoobar' declared here}}
};
}
void Check() { // expected-note{{'Check' declared here}}
if (toFoobar()) Double(7); // expected-error{{use of undeclared identifier 'toFoobar'; did you mean 'barstool::toFoobar'?}}
if (noFoobar()) Double(7); // expected-error{{use of undeclared identifier 'noFoobar'; did you mean 'barstool::toFoobar'?}}
if (moreFoobar()) Double(7); // expected-error{{use of undeclared identifier 'moreFoobar'; did you mean 'fizbin::nested::moreFoobar'}}
if (lessFoobar()) Double(7); // expected-error{{use of undeclared identifier 'lessFoobar'; did you mean 'fizbin::nested::lessFoobar'?}}
if (baztool::toFoobar()) Double(7); // expected-error{{use of undeclared identifier 'baztool'; did you mean 'fizbin::baztool'?}}
if (nested::moreFoobar()) Double(7); // expected-error{{use of undeclared identifier 'nested'; did you mean 'fizbin::nested'?}}
if (dummy::moreFoobar()) Double(7); // expected-error{{use of undeclared identifier 'dummy'; did you mean 'fizbin::dummy'?}}
if (dummy::mreFoobar()) Double(7); // expected-error{{use of undeclared identifier 'dummy'; did you mean 'fizbin::dummy'?}} \
// expected-error{{no member named 'mreFoobar' in 'fizbin::dummy'; did you mean 'moreFoobar'?}}
if (moFoobin()) Double(7); // expected-error{{use of undeclared identifier 'moFoobin'}}
}
void Alt() {
Cleck(); // expected-error{{{use of undeclared identifier 'Cleck'; did you mean 'Check'?}}
}
namespace N {
namespace inner {
class myvector { /* ... */ }; // expected-note{{'inner::myvector' declared here}}
}
void f() {
myvector v; // expected-error{{no type named 'myvector' in namespace 'N::inner'; did you mean 'inner::myvector'?}}
}
}
namespace realstd {
inline namespace __1 {
class mylinkedlist { /* ... */ }; // expected-note 2 {{'realstd::mylinkedlist' declared here}}
}
class linkedlist { /* ... */ };
}
void f() {
mylinkedlist v; // expected-error{{no type named 'mylinkedlist' in namespace 'realstd'; did you mean 'realstd::mylinkedlist'?}}
nylinkedlist w; // expected-error{{no type named 'nylinkedlist' in namespace 'realstd'; did you mean 'realstd::mylinkedlist'?}}
}

View File

@ -1,6 +1,6 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
@interface Sprite {
@interface Sprite { // expected-note{{'Sprite' declared here}}
int sprite, spree;
int UseGlobalBar;
}
@ -17,7 +17,8 @@ int UseGlobalBar;
+ (void)setFoo:(int)foo {
sprite = foo; // expected-error {{instance variable 'sprite' accessed in class method}}
spree = foo;
Xsprite = foo; // expected-error {{use of undeclared identifier 'Xsprite'}}
Xsprite = foo; // expected-error {{unknown type name 'Xsprite'; did you mean 'Sprite'?}} \
// expected-error{{expected identifier or '('}}
UseGlobalBar = 10;
}
+ (void)setSprite:(int)sprite {