aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Sema/ExternalSemaSource.h5
-rw-r--r--include/clang/Sema/Sema.h29
-rw-r--r--include/clang/Sema/TypoCorrection.h105
-rw-r--r--include/clang/Serialization/ASTBitCodes.h6
-rw-r--r--include/clang/Serialization/ASTReader.h8
-rw-r--r--lib/Sema/Sema.cpp6
-rw-r--r--lib/Sema/SemaCXXScopeSpec.cpp31
-rw-r--r--lib/Sema/SemaDecl.cpp78
-rw-r--r--lib/Sema/SemaDeclCXX.cpp111
-rw-r--r--lib/Sema/SemaDeclObjC.cpp33
-rw-r--r--lib/Sema/SemaExpr.cpp41
-rw-r--r--lib/Sema/SemaExprMember.cpp38
-rw-r--r--lib/Sema/SemaExprObjC.cpp28
-rw-r--r--lib/Sema/SemaInit.cpp20
-rw-r--r--lib/Sema/SemaLookup.cpp851
-rw-r--r--lib/Sema/SemaTemplate.cpp25
-rw-r--r--lib/Sema/SemaTemplateVariadic.cpp16
-rw-r--r--lib/Serialization/ASTReader.cpp20
-rw-r--r--lib/Serialization/ASTWriter.cpp16
-rw-r--r--test/CXX/basic/basic.lookup/basic.lookup.argdep/p4.cpp13
-rw-r--r--test/FixIt/typo.cpp6
-rw-r--r--test/PCH/Inputs/typo.hpp8
-rw-r--r--test/PCH/typo.cpp17
-rw-r--r--test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp61
-rw-r--r--test/SemaObjC/ivar-ref-misuse.m5
25 files changed, 1060 insertions, 517 deletions
diff --git a/include/clang/Sema/ExternalSemaSource.h b/include/clang/Sema/ExternalSemaSource.h
index e2b083e830..072e1b58d1 100644
--- a/include/clang/Sema/ExternalSemaSource.h
+++ b/include/clang/Sema/ExternalSemaSource.h
@@ -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.
///
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 2e51117f26..65ce34a7a2 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -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.
diff --git a/include/clang/Sema/TypoCorrection.h b/include/clang/Sema/TypoCorrection.h
new file mode 100644
index 0000000000..9965953538
--- /dev/null
+++ b/include/clang/Sema/TypoCorrection.h
@@ -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
diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h
index 15fe3c61ae..a4e90aa265 100644
--- a/include/clang/Serialization/ASTBitCodes.h
+++ b/include/clang/Serialization/ASTBitCodes.h
@@ -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
};
diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h
index 8923e2ab0d..a6c32aafd3 100644
--- a/include/clang/Serialization/ASTReader.h
+++ b/include/clang/Serialization/ASTReader.h
@@ -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);
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index 7d22031ecb..9550f9aad2 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -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();
diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp
index 61d9e93f2f..e54857196a 100644
--- a/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/lib/Sema/SemaCXXScopeSpec.cpp
@@ -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);
}
}
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index efb06f6687..2779faeb15 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -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());
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index c0d34da922..ac51138b91 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -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;
}
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index a3f53ec234..a9f4f95c20 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -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)