mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-12-14 03:29:57 +00:00
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:
parent
d79f9666c8
commit
c2fa169d6c
@ -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.
|
||||
///
|
||||
|
@ -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.
|
||||
|
105
clang/include/clang/Sema/TypoCorrection.h
Normal file
105
clang/include/clang/Sema/TypoCorrection.h
Normal 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
|
@ -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
|
||||
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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 (?)
|
||||
|
@ -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()
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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'?}}
|
||||
|
8
clang/test/PCH/Inputs/typo.hpp
Normal file
8
clang/test/PCH/Inputs/typo.hpp
Normal 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
17
clang/test/PCH/typo.cpp
Normal 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
|
@ -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'?}}
|
||||
}
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user