[cfe-commits] r134007 - in /cfe/trunk: include/clang/Sema/ include/clang/Serialization/ lib/Sema/ lib/Serialization/ test/CXX/basic/basic.lookup/basic.lookup.argdep/ test/FixIt/ test/PCH/ test/PCH/Inputs/ test/SemaCXX/ test/SemaObjC/
Chad Rosier
mcrosier at apple.com
Tue Jun 28 12:36:24 PDT 2011
Doug,
I believe this is causing a make failure due to:
llvm[4]: Compiling ASTLocation.cpp for Release+Asserts build
/usr/include/c++/4.2.1/bits/stl_map.h: In member function '_Tp& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const _Key&) [with _Key = unsigned int, _Tp = llvm::StringMap<clang::TypoCorrection, llvm::BumpPtrAllocator>, _Compare = std::less<unsigned int>, _Alloc = std::allocator<std::pair<const unsigned int, llvm::StringMap<clang::TypoCorrection, llvm::BumpPtrAllocator> > >]':
/lib/Sema/SemaLookup.cpp:3170: instantiated from here
/usr/include/c++/4.2.1/bits/stl_map.h:350: error: no matching function for call to 'llvm::StringMap<clang::TypoCorrection, llvm::BumpPtrAllocator>::StringMap(llvm::StringMap<clang::TypoCorrection, llvm::BumpPtrAllocator>)'
Please take a look.
Chad
On Jun 28, 2011, at 9:20 AM, Douglas Gregor wrote:
> Author: dgregor
> Date: Tue Jun 28 11:20:02 2011
> New Revision: 134007
>
> URL: http://llvm.org/viewvc/llvm-project?rev=134007&view=rev
> Log:
> 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!
>
> Added:
> cfe/trunk/include/clang/Sema/TypoCorrection.h (with props)
> cfe/trunk/test/PCH/Inputs/typo.hpp (with props)
> cfe/trunk/test/PCH/typo.cpp (with props)
> cfe/trunk/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp (with props)
> Modified:
> cfe/trunk/include/clang/Sema/ExternalSemaSource.h
> cfe/trunk/include/clang/Sema/Sema.h
> cfe/trunk/include/clang/Serialization/ASTBitCodes.h
> cfe/trunk/include/clang/Serialization/ASTReader.h
> cfe/trunk/lib/Sema/Sema.cpp
> cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp
> cfe/trunk/lib/Sema/SemaDecl.cpp
> cfe/trunk/lib/Sema/SemaDeclCXX.cpp
> cfe/trunk/lib/Sema/SemaDeclObjC.cpp
> cfe/trunk/lib/Sema/SemaExpr.cpp
> cfe/trunk/lib/Sema/SemaExprMember.cpp
> cfe/trunk/lib/Sema/SemaExprObjC.cpp
> cfe/trunk/lib/Sema/SemaInit.cpp
> cfe/trunk/lib/Sema/SemaLookup.cpp
> cfe/trunk/lib/Sema/SemaTemplate.cpp
> cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
> cfe/trunk/lib/Serialization/ASTReader.cpp
> cfe/trunk/lib/Serialization/ASTWriter.cpp
> cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4.cpp
> cfe/trunk/test/FixIt/typo.cpp
> cfe/trunk/test/SemaObjC/ivar-ref-misuse.m
>
> Modified: cfe/trunk/include/clang/Sema/ExternalSemaSource.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/ExternalSemaSource.h?rev=134007&r1=134006&r2=134007&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Sema/ExternalSemaSource.h (original)
> +++ cfe/trunk/include/clang/Sema/ExternalSemaSource.h Tue Jun 28 11:20:02 2011
> @@ -49,6 +49,11 @@
> /// 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.
> ///
>
> Modified: cfe/trunk/include/clang/Sema/Sema.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=134007&r1=134006&r2=134007&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Sema/Sema.h (original)
> +++ cfe/trunk/include/clang/Sema/Sema.h Tue Jun 28 11:20:02 2011
> @@ -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 @@
> class ASTConsumer;
> class ASTContext;
> class ASTMutationListener;
> + class ASTReader;
> + class ASTWriter;
> class ArrayType;
> class AttributeList;
> class BlockDecl;
> @@ -1623,6 +1626,16 @@
> 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 @@
> 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 @@
> /// \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 @@
> protected:
> friend class Parser;
> friend class InitializationSequence;
> + friend class ASTReader;
> + friend class ASTWriter;
>
> public:
> /// \brief Retrieve the parser's current scope.
>
> Added: cfe/trunk/include/clang/Sema/TypoCorrection.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/TypoCorrection.h?rev=134007&view=auto
> ==============================================================================
> --- cfe/trunk/include/clang/Sema/TypoCorrection.h (added)
> +++ cfe/trunk/include/clang/Sema/TypoCorrection.h Tue Jun 28 11:20:02 2011
> @@ -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
>
> Propchange: cfe/trunk/include/clang/Sema/TypoCorrection.h
> ------------------------------------------------------------------------------
> svn:eol-style = native
>
> Propchange: cfe/trunk/include/clang/Sema/TypoCorrection.h
> ------------------------------------------------------------------------------
> svn:keywords = Id
>
> Propchange: cfe/trunk/include/clang/Sema/TypoCorrection.h
> ------------------------------------------------------------------------------
> svn:mime-type = text/plain
>
> Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=134007&r1=134006&r2=134007&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original)
> +++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Tue Jun 28 11:20:02 2011
> @@ -371,7 +371,11 @@
>
> /// \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
>
> };
>
>
> Modified: cfe/trunk/include/clang/Serialization/ASTReader.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTReader.h?rev=134007&r1=134006&r2=134007&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Serialization/ASTReader.h (original)
> +++ cfe/trunk/include/clang/Serialization/ASTReader.h Tue Jun 28 11:20:02 2011
> @@ -625,6 +625,9 @@
> /// \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 @@
> 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);
>
>
> Modified: cfe/trunk/lib/Sema/Sema.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=134007&r1=134006&r2=134007&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/Sema.cpp (original)
> +++ cfe/trunk/lib/Sema/Sema.cpp Tue Jun 28 11:20:02 2011
> @@ -154,6 +154,8 @@
> AnalysisWarnings(*this)
> {
> TUScope = 0;
> + LoadedExternalKnownNamespaces = false;
> +
> if (getLangOptions().CPlusPlus)
> FieldCollector.reset(new CXXFieldCollector());
>
> @@ -778,6 +780,10 @@
> 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();
>
> Modified: cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp?rev=134007&r1=134006&r2=134007&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp Tue Jun 28 11:20:02 2011
> @@ -464,26 +464,29 @@
> // 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);
> }
> }
>
> Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=134007&r1=134006&r2=134007&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Jun 28 11:20:02 2011
> @@ -287,41 +287,42 @@
>
> // 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 @@
> // 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 @@
> 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 @@
> /// 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());
>
> Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=134007&r1=134006&r2=134007&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Tue Jun 28 11:20:02 2011
> @@ -1426,25 +1426,27 @@
> }
>
> // 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 @@
> // 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 @@
> // 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 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 @@
> 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 @@
> 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 @@
> 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;
> }
>
> Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=134007&r1=134006&r2=134007&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Tue Jun 28 11:20:02 2011
> @@ -442,9 +442,10 @@
>
> 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 @@
> 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 @@
> } 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;
>
> Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=134007&r1=134006&r2=134007&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Jun 28 11:20:02 2011
> @@ -1397,39 +1397,44 @@
> }
>
> // 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 @@
> // 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 (?)
>
> Modified: cfe/trunk/lib/Sema/SemaExprMember.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprMember.cpp?rev=134007&r1=134006&r2=134007&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaExprMember.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExprMember.cpp Tue Jun 28 11:20:02 2011
> @@ -555,20 +555,24 @@
> // 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 @@
> // 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()
>
> Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=134007&r1=134006&r2=134007&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Tue Jun 28 11:20:02 2011
> @@ -663,14 +663,15 @@
> }
>
> // 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 @@
> 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;
> }
>
> Modified: cfe/trunk/lib/Sema/SemaInit.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=134007&r1=134006&r2=134007&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaInit.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaInit.cpp Tue Jun 28 11:20:02 2011
> @@ -1443,19 +1443,23 @@
> // 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;
>
> Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=134007&r1=134006&r2=134007&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaLookup.cpp Tue Jun 28 11:20:02 2011
> @@ -20,6 +20,7 @@
> #include "clang/Sema/ScopeInfo.h"
> #include "clang/Sema/TemplateDeduction.h"
> #include "clang/Sema/ExternalSemaSource.h"
> +#include "clang/Sema/TypoCorrection.h"
> #include "clang/AST/ASTContext.h"
> #include "clang/AST/CXXInheritance.h"
> #include "clang/AST/Decl.h"
> @@ -42,6 +43,7 @@
> #include <iterator>
> #include <utility>
> #include <algorithm>
> +#include <map>
>
> using namespace clang;
> using namespace sema;
> @@ -3041,6 +3043,12 @@
> //===----------------------------------------------------------------------===//
>
> namespace {
> +
> +typedef llvm::StringMap<TypoCorrection, llvm::BumpPtrAllocator> TypoResultsMap;
> +typedef std::map<unsigned, TypoResultsMap> TypoEditDistanceMap;
> +
> +static const unsigned MaxTypoDistanceResultSets = 5;
> +
> class TypoCorrectionConsumer : public VisibleDeclConsumer {
> /// \brief The name written that is a typo in the source.
> llvm::StringRef Typo;
> @@ -3048,33 +3056,47 @@
> /// \brief The results found that have the smallest edit distance
> /// found (so far) with the typo name.
> ///
> - /// The boolean value indicates whether there is a keyword with this name.
> - llvm::StringMap<bool, llvm::BumpPtrAllocator> BestResults;
> + /// The pointer value being set to the current DeclContext indicates
> + /// whether there is a keyword with this name.
> + TypoEditDistanceMap BestResults;
>
> - /// \brief The best edit distance found so far.
> - unsigned BestEditDistance;
> + /// \brief The worst of the best N edit distances found so far.
> + unsigned MaxEditDistance;
> +
> + Sema &SemaRef;
>
> public:
> - explicit TypoCorrectionConsumer(IdentifierInfo *Typo)
> + explicit TypoCorrectionConsumer(Sema &SemaRef, IdentifierInfo *Typo)
> : Typo(Typo->getName()),
> - BestEditDistance((std::numeric_limits<unsigned>::max)()) { }
> + MaxEditDistance((std::numeric_limits<unsigned>::max)()),
> + SemaRef(SemaRef) { }
>
> virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, bool InBaseClass);
> void FoundName(llvm::StringRef Name);
> - void addKeywordResult(ASTContext &Context, llvm::StringRef Keyword);
> -
> - typedef llvm::StringMap<bool, llvm::BumpPtrAllocator>::iterator iterator;
> - iterator begin() { return BestResults.begin(); }
> - iterator end() { return BestResults.end(); }
> - void erase(iterator I) { BestResults.erase(I); }
> + void addKeywordResult(llvm::StringRef Keyword);
> + void addName(llvm::StringRef Name, NamedDecl *ND, unsigned Distance,
> + NestedNameSpecifier *NNS=NULL);
> + void addCorrection(TypoCorrection Correction);
> +
> + typedef TypoResultsMap::iterator result_iterator;
> + typedef TypoEditDistanceMap::iterator distance_iterator;
> + distance_iterator begin() { return BestResults.begin(); }
> + distance_iterator end() { return BestResults.end(); }
> + void erase(distance_iterator I) { BestResults.erase(I); }
> unsigned size() const { return BestResults.size(); }
> bool empty() const { return BestResults.empty(); }
>
> - bool &operator[](llvm::StringRef Name) {
> - return BestResults[Name];
> + TypoCorrection &operator[](llvm::StringRef Name) {
> + return BestResults.begin()->second[Name];
> }
>
> - unsigned getBestEditDistance() const { return BestEditDistance; }
> + unsigned getMaxEditDistance() const {
> + return MaxEditDistance;
> + }
> +
> + unsigned getBestEditDistance() {
> + return (BestResults.empty()) ? MaxEditDistance : BestResults.begin()->first;
> + }
> };
>
> }
> @@ -3099,55 +3121,164 @@
> // Use a simple length-based heuristic to determine the minimum possible
> // edit distance. If the minimum isn't good enough, bail out early.
> unsigned MinED = abs((int)Name.size() - (int)Typo.size());
> - if (MinED > BestEditDistance || (MinED && Typo.size() / MinED < 3))
> + if (MinED > MaxEditDistance || (MinED && Typo.size() / MinED < 3))
> return;
>
> // Compute an upper bound on the allowable edit distance, so that the
> // edit-distance algorithm can short-circuit.
> unsigned UpperBound =
> - std::min(unsigned((Typo.size() + 2) / 3), BestEditDistance);
> + std::min(unsigned((Typo.size() + 2) / 3), MaxEditDistance);
>
> // Compute the edit distance between the typo and the name of this
> // entity. If this edit distance is not worse than the best edit
> // distance we've seen so far, add it to the list of results.
> unsigned ED = Typo.edit_distance(Name, true, UpperBound);
> - if (ED == 0)
> - return;
>
> - if (ED < BestEditDistance) {
> - // This result is better than any we've seen before; clear out
> - // the previous results.
> - BestResults.clear();
> - BestEditDistance = ED;
> - } else if (ED > BestEditDistance) {
> + if (ED > MaxEditDistance) {
> // This result is worse than the best results we've seen so far;
> // ignore it.
> return;
> }
>
> - // Add this name to the list of results. By not assigning a value, we
> - // keep the current value if we've seen this name before (either as a
> - // keyword or as a declaration), or get the default value (not a keyword)
> - // if we haven't seen it before.
> - (void)BestResults[Name];
> + addName(Name, NULL, ED);
> }
>
> -void TypoCorrectionConsumer::addKeywordResult(ASTContext &Context,
> - llvm::StringRef Keyword) {
> +void TypoCorrectionConsumer::addKeywordResult(llvm::StringRef Keyword) {
> // Compute the edit distance between the typo and this keyword.
> // If this edit distance is not worse than the best edit
> // distance we've seen so far, add it to the list of results.
> unsigned ED = Typo.edit_distance(Keyword);
> - if (ED < BestEditDistance) {
> - BestResults.clear();
> - BestEditDistance = ED;
> - } else if (ED > BestEditDistance) {
> + if (ED > MaxEditDistance) {
> // This result is worse than the best results we've seen so far;
> // ignore it.
> return;
> }
>
> - BestResults[Keyword] = true;
> + addName(Keyword, TypoCorrection::KeywordDecl(), ED);
> +}
> +
> +void TypoCorrectionConsumer::addName(llvm::StringRef Name,
> + NamedDecl *ND,
> + unsigned Distance,
> + NestedNameSpecifier *NNS) {
> + addCorrection(TypoCorrection(&SemaRef.Context.Idents.get(Name),
> + ND, NNS, Distance));
> +}
> +
> +void TypoCorrectionConsumer::addCorrection(TypoCorrection Correction) {
> + llvm::StringRef Name = Correction.getCorrectionAsIdentifierInfo()->getName();
> + BestResults[Correction.getEditDistance()][Name] = Correction;
> +
> + while (BestResults.size() > MaxTypoDistanceResultSets) {
> + BestResults.erase(--BestResults.end());
> + }
> +}
> +
> +namespace {
> +
> +class SpecifierInfo {
> + public:
> + DeclContext* DeclCtx;
> + NestedNameSpecifier* NameSpecifier;
> + unsigned EditDistance;
> +
> + SpecifierInfo(DeclContext *Ctx, NestedNameSpecifier *NNS, unsigned ED)
> + : DeclCtx(Ctx), NameSpecifier(NNS), EditDistance(ED) {}
> +};
> +
> +typedef llvm::SmallVector<DeclContext*, 4> DeclContextList;
> +typedef llvm::SmallVector<SpecifierInfo, 16> SpecifierInfoList;
> +
> +class NamespaceSpecifierSet {
> + ASTContext &Context;
> + DeclContextList CurContextChain;
> + bool isSorted;
> +
> + SpecifierInfoList Specifiers;
> + llvm::SmallSetVector<unsigned, 4> Distances;
> + llvm::DenseMap<unsigned, SpecifierInfoList> DistanceMap;
> +
> + /// \brief Helper for building the list of DeclContexts between the current
> + /// context and the top of the translation unit
> + static DeclContextList BuildContextChain(DeclContext *Start);
> +
> + void SortNamespaces();
> +
> + public:
> + explicit NamespaceSpecifierSet(ASTContext &Context, DeclContext *CurContext)
> + : Context(Context), CurContextChain(BuildContextChain(CurContext)) {}
> +
> + /// \brief Add the namespace to the set, computing the corresponding
> + /// NestedNameSpecifier and its distance in the process.
> + void AddNamespace(NamespaceDecl *ND);
> +
> + typedef SpecifierInfoList::iterator iterator;
> + iterator begin() {
> + if (!isSorted) SortNamespaces();
> + return Specifiers.begin();
> + }
> + iterator end() { return Specifiers.end(); }
> +};
> +
> +}
> +
> +DeclContextList NamespaceSpecifierSet::BuildContextChain(DeclContext *Start) {
> + DeclContextList Chain;
> + for (DeclContext *DC = Start->getPrimaryContext(); DC != NULL;
> + DC = DC->getLookupParent()) {
> + NamespaceDecl *ND = dyn_cast_or_null<NamespaceDecl>(DC);
> + if (!DC->isInlineNamespace() && !DC->isTransparentContext() &&
> + !(ND && ND->isAnonymousNamespace()))
> + Chain.push_back(DC->getPrimaryContext());
> + }
> + return Chain;
> +}
> +
> +void NamespaceSpecifierSet::SortNamespaces() {
> + llvm::SmallVector<unsigned, 4> sortedDistances;
> + sortedDistances.append(Distances.begin(), Distances.end());
> +
> + if (sortedDistances.size() > 1)
> + std::sort(sortedDistances.begin(), sortedDistances.end());
> +
> + Specifiers.clear();
> + for (llvm::SmallVector<unsigned, 4>::iterator DI = sortedDistances.begin(),
> + DIEnd = sortedDistances.end();
> + DI != DIEnd; ++DI) {
> + SpecifierInfoList &SpecList = DistanceMap[*DI];
> + Specifiers.append(SpecList.begin(), SpecList.end());
> + }
> +
> + isSorted = true;
> +}
> +
> +void NamespaceSpecifierSet::AddNamespace(NamespaceDecl *ND) {
> + DeclContext *Ctx = dyn_cast<DeclContext>(ND);
> + NestedNameSpecifier *NNS = NULL;
> + unsigned NumSpecifiers = 0;
> + DeclContextList NamespaceDeclChain(BuildContextChain(Ctx));
> +
> + // Eliminate common elements from the two DeclContext chains
> + for (DeclContextList::reverse_iterator C = CurContextChain.rbegin(),
> + CEnd = CurContextChain.rend();
> + C != CEnd && NamespaceDeclChain.back() == *C; ++C) {
> + NamespaceDeclChain.pop_back();
> + }
> +
> + // Build the NestedNameSpecifier from what is left of the NamespaceDeclChain
> + for (DeclContextList::reverse_iterator C = NamespaceDeclChain.rbegin(),
> + CEnd = NamespaceDeclChain.rend();
> + C != CEnd; ++C) {
> + NamespaceDecl *ND = dyn_cast_or_null<NamespaceDecl>(*C);
> + if (ND) {
> + NNS = NestedNameSpecifier::Create(Context, NNS, ND);
> + ++NumSpecifiers;
> + }
> + }
> +
> + isSorted = false;
> + Distances.insert(NumSpecifiers);
> + DistanceMap[NumSpecifiers].push_back(SpecifierInfo(Ctx, NNS, NumSpecifiers));
> }
>
> /// \brief Perform name lookup for a possible result for typo correction.
> @@ -3201,177 +3332,60 @@
> }
> }
>
> -/// \brief Try to "correct" a typo in the source code by finding
> -/// visible declarations whose names are similar to the name that was
> -/// present in the source code.
> -///
> -/// \param Res the \c LookupResult structure that contains the name
> -/// that was present in the source code along with the name-lookup
> -/// criteria used to search for the name. On success, this structure
> -/// will contain the results of name lookup.
> -///
> -/// \param S the scope in which name lookup occurs.
> -///
> -/// \param SS the nested-name-specifier that precedes the name we're
> -/// looking for, if present.
> -///
> -/// \param MemberContext if non-NULL, the context in which to look for
> -/// a member access expression.
> -///
> -/// \param EnteringContext whether we're entering the context described by
> -/// the nested-name-specifier SS.
> -///
> -/// \param CTC The context in which typo correction occurs, which impacts the
> -/// set of keywords permitted.
> -///
> -/// \param OPT when non-NULL, the search for visible declarations will
> -/// also walk the protocols in the qualified interfaces of \p OPT.
> -///
> -/// \returns the corrected name if the typo was corrected, otherwise returns an
> -/// empty \c DeclarationName. When a typo was corrected, the result structure
> -/// may contain the results of name lookup for the correct name or it may be
> -/// empty.
> -DeclarationName Sema::CorrectTypo(LookupResult &Res, Scope *S, CXXScopeSpec *SS,
> - DeclContext *MemberContext,
> - bool EnteringContext,
> - CorrectTypoContext CTC,
> - const ObjCObjectPointerType *OPT) {
> - if (Diags.hasFatalErrorOccurred() || !getLangOptions().SpellChecking)
> - return DeclarationName();
> -
> - // We only attempt to correct typos for identifiers.
> - IdentifierInfo *Typo = Res.getLookupName().getAsIdentifierInfo();
> - if (!Typo)
> - return DeclarationName();
> -
> - // If the scope specifier itself was invalid, don't try to correct
> - // typos.
> - if (SS && SS->isInvalid())
> - return DeclarationName();
> -
> - // Never try to correct typos during template deduction or
> - // instantiation.
> - if (!ActiveTemplateInstantiations.empty())
> - return DeclarationName();
> -
> - TypoCorrectionConsumer Consumer(Typo);
> -
> - // Perform name lookup to find visible, similarly-named entities.
> - bool IsUnqualifiedLookup = false;
> - if (MemberContext) {
> - LookupVisibleDecls(MemberContext, Res.getLookupKind(), Consumer);
> -
> - // Look in qualified interfaces.
> - if (OPT) {
> - for (ObjCObjectPointerType::qual_iterator
> - I = OPT->qual_begin(), E = OPT->qual_end();
> - I != E; ++I)
> - LookupVisibleDecls(*I, Res.getLookupKind(), Consumer);
> - }
> - } else if (SS && SS->isSet()) {
> - DeclContext *DC = computeDeclContext(*SS, EnteringContext);
> - if (!DC)
> - return DeclarationName();
> -
> - // Provide a stop gap for files that are just seriously broken. Trying
> - // to correct all typos can turn into a HUGE performance penalty, causing
> - // some files to take minutes to get rejected by the parser.
> - if (TyposCorrected + UnqualifiedTyposCorrected.size() >= 20)
> - return DeclarationName();
> - ++TyposCorrected;
> -
> - LookupVisibleDecls(DC, Res.getLookupKind(), Consumer);
> - } else {
> - IsUnqualifiedLookup = true;
> - UnqualifiedTyposCorrectedMap::iterator Cached
> - = UnqualifiedTyposCorrected.find(Typo);
> - if (Cached == UnqualifiedTyposCorrected.end()) {
> - // Provide a stop gap for files that are just seriously broken. Trying
> - // to correct all typos can turn into a HUGE performance penalty, causing
> - // some files to take minutes to get rejected by the parser.
> - if (TyposCorrected + UnqualifiedTyposCorrected.size() >= 20)
> - return DeclarationName();
> -
> - // For unqualified lookup, look through all of the names that we have
> - // seen in this translation unit.
> - for (IdentifierTable::iterator I = Context.Idents.begin(),
> - IEnd = Context.Idents.end();
> - I != IEnd; ++I)
> - Consumer.FoundName(I->getKey());
> -
> - // Walk through identifiers in external identifier sources.
> - if (IdentifierInfoLookup *External
> - = Context.Idents.getExternalIdentifierLookup()) {
> - llvm::OwningPtr<IdentifierIterator> Iter(External->getIdentifiers());
> - do {
> - llvm::StringRef Name = Iter->Next();
> - if (Name.empty())
> - break;
> -
> - Consumer.FoundName(Name);
> - } while (true);
> - }
> - } else {
> - // Use the cached value, unless it's a keyword. In the keyword case, we'll
> - // end up adding the keyword below.
> - if (Cached->second.first.empty())
> - return DeclarationName();
> -
> - if (!Cached->second.second)
> - Consumer.FoundName(Cached->second.first);
> - }
> - }
> -
> +/// \brief Add keywords to the consumer as possible typo corrections.
> +static void AddKeywordsToConsumer(Sema &SemaRef,
> + TypoCorrectionConsumer &Consumer,
> + Scope *S, Sema::CorrectTypoContext CTC) {
> // Add context-dependent keywords.
> bool WantTypeSpecifiers = false;
> bool WantExpressionKeywords = false;
> bool WantCXXNamedCasts = false;
> bool WantRemainingKeywords = false;
> switch (CTC) {
> - case CTC_Unknown:
> + case Sema::CTC_Unknown:
> WantTypeSpecifiers = true;
> WantExpressionKeywords = true;
> WantCXXNamedCasts = true;
> WantRemainingKeywords = true;
>
> - if (ObjCMethodDecl *Method = getCurMethodDecl())
> + if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl())
> if (Method->getClassInterface() &&
> Method->getClassInterface()->getSuperClass())
> - Consumer.addKeywordResult(Context, "super");
> + Consumer.addKeywordResult("super");
>
> break;
>
> - case CTC_NoKeywords:
> + case Sema::CTC_NoKeywords:
> break;
>
> - case CTC_Type:
> + case Sema::CTC_Type:
> WantTypeSpecifiers = true;
> break;
>
> - case CTC_ObjCMessageReceiver:
> - Consumer.addKeywordResult(Context, "super");
> + case Sema::CTC_ObjCMessageReceiver:
> + Consumer.addKeywordResult("super");
> // Fall through to handle message receivers like expressions.
>
> - case CTC_Expression:
> - if (getLangOptions().CPlusPlus)
> + case Sema::CTC_Expression:
> + if (SemaRef.getLangOptions().CPlusPlus)
> WantTypeSpecifiers = true;
> WantExpressionKeywords = true;
> // Fall through to get C++ named casts.
>
> - case CTC_CXXCasts:
> + case Sema::CTC_CXXCasts:
> WantCXXNamedCasts = true;
> break;
>
> - case CTC_ObjCPropertyLookup:
> + case Sema::CTC_ObjCPropertyLookup:
> // FIXME: Add "isa"?
> break;
>
> - case CTC_MemberLookup:
> - if (getLangOptions().CPlusPlus)
> - Consumer.addKeywordResult(Context, "template");
> + case Sema::CTC_MemberLookup:
> + if (SemaRef.getLangOptions().CPlusPlus)
> + Consumer.addKeywordResult("template");
> break;
>
> - case CTC_ObjCIvarLookup:
> + case Sema::CTC_ObjCIvarLookup:
> break;
> }
>
> @@ -3387,240 +3401,449 @@
>
> const unsigned NumCTypeSpecs = sizeof(CTypeSpecs) / sizeof(CTypeSpecs[0]);
> for (unsigned I = 0; I != NumCTypeSpecs; ++I)
> - Consumer.addKeywordResult(Context, CTypeSpecs[I]);
> + Consumer.addKeywordResult(CTypeSpecs[I]);
>
> - if (getLangOptions().C99)
> - Consumer.addKeywordResult(Context, "restrict");
> - if (getLangOptions().Bool || getLangOptions().CPlusPlus)
> - Consumer.addKeywordResult(Context, "bool");
> + if (SemaRef.getLangOptions().C99)
> + Consumer.addKeywordResult("restrict");
> + if (SemaRef.getLangOptions().Bool || SemaRef.getLangOptions().CPlusPlus)
> + Consumer.addKeywordResult("bool");
>
> - if (getLangOptions().CPlusPlus) {
> - Consumer.addKeywordResult(Context, "class");
> - Consumer.addKeywordResult(Context, "typename");
> - Consumer.addKeywordResult(Context, "wchar_t");
> + if (SemaRef.getLangOptions().CPlusPlus) {
> + Consumer.addKeywordResult("class");
> + Consumer.addKeywordResult("typename");
> + Consumer.addKeywordResult("wchar_t");
>
> - if (getLangOptions().CPlusPlus0x) {
> - Consumer.addKeywordResult(Context, "char16_t");
> - Consumer.addKeywordResult(Context, "char32_t");
> - Consumer.addKeywordResult(Context, "constexpr");
> - Consumer.addKeywordResult(Context, "decltype");
> - Consumer.addKeywordResult(Context, "thread_local");
> + if (SemaRef.getLangOptions().CPlusPlus0x) {
> + Consumer.addKeywordResult("char16_t");
> + Consumer.addKeywordResult("char32_t");
> + Consumer.addKeywordResult("constexpr");
> + Consumer.addKeywordResult("decltype");
> + Consumer.addKeywordResult("thread_local");
> }
> }
>
> - if (getLangOptions().GNUMode)
> - Consumer.addKeywordResult(Context, "typeof");
> + if (SemaRef.getLangOptions().GNUMode)
> + Consumer.addKeywordResult("typeof");
> }
>
> - if (WantCXXNamedCasts && getLangOptions().CPlusPlus) {
> - Consumer.addKeywordResult(Context, "const_cast");
> - Consumer.addKeywordResult(Context, "dynamic_cast");
> - Consumer.addKeywordResult(Context, "reinterpret_cast");
> - Consumer.addKeywordResult(Context, "static_cast");
> + if (WantCXXNamedCasts && SemaRef.getLangOptions().CPlusPlus) {
> + Consumer.addKeywordResult("const_cast");
> + Consumer.addKeywordResult("dynamic_cast");
> + Consumer.addKeywordResult("reinterpret_cast");
> + Consumer.addKeywordResult("static_cast");
> }
>
> if (WantExpressionKeywords) {
> - Consumer.addKeywordResult(Context, "sizeof");
> - if (getLangOptions().Bool || getLangOptions().CPlusPlus) {
> - Consumer.addKeywordResult(Context, "false");
> - Consumer.addKeywordResult(Context, "true");
> + Consumer.addKeywordResult("sizeof");
> + if (SemaRef.getLangOptions().Bool || SemaRef.getLangOptions().CPlusPlus) {
> + Consumer.addKeywordResult("false");
> + Consumer.addKeywordResult("true");
> }
>
> - if (getLangOptions().CPlusPlus) {
> + if (SemaRef.getLangOptions().CPlusPlus) {
> const char *CXXExprs[] = {
> "delete", "new", "operator", "throw", "typeid"
> };
> const unsigned NumCXXExprs = sizeof(CXXExprs) / sizeof(CXXExprs[0]);
> for (unsigned I = 0; I != NumCXXExprs; ++I)
> - Consumer.addKeywordResult(Context, CXXExprs[I]);
> + Consumer.addKeywordResult(CXXExprs[I]);
>
> - if (isa<CXXMethodDecl>(CurContext) &&
> - cast<CXXMethodDecl>(CurContext)->isInstance())
> - Consumer.addKeywordResult(Context, "this");
> -
> - if (getLangOptions().CPlusPlus0x) {
> - Consumer.addKeywordResult(Context, "alignof");
> - Consumer.addKeywordResult(Context, "nullptr");
> + if (isa<CXXMethodDecl>(SemaRef.CurContext) &&
> + cast<CXXMethodDecl>(SemaRef.CurContext)->isInstance())
> + Consumer.addKeywordResult("this");
> +
> + if (SemaRef.getLangOptions().CPlusPlus0x) {
> + Consumer.addKeywordResult("alignof");
> + Consumer.addKeywordResult("nullptr");
> }
> }
> }
>
> if (WantRemainingKeywords) {
> - if (getCurFunctionOrMethodDecl() || getCurBlock()) {
> + if (SemaRef.getCurFunctionOrMethodDecl() || SemaRef.getCurBlock()) {
> // Statements.
> const char *CStmts[] = {
> "do", "else", "for", "goto", "if", "return", "switch", "while" };
> const unsigned NumCStmts = sizeof(CStmts) / sizeof(CStmts[0]);
> for (unsigned I = 0; I != NumCStmts; ++I)
> - Consumer.addKeywordResult(Context, CStmts[I]);
> + Consumer.addKeywordResult(CStmts[I]);
>
> - if (getLangOptions().CPlusPlus) {
> - Consumer.addKeywordResult(Context, "catch");
> - Consumer.addKeywordResult(Context, "try");
> + if (SemaRef.getLangOptions().CPlusPlus) {
> + Consumer.addKeywordResult("catch");
> + Consumer.addKeywordResult("try");
> }
>
> if (S && S->getBreakParent())
> - Consumer.addKeywordResult(Context, "break");
> + Consumer.addKeywordResult("break");
>
> if (S && S->getContinueParent())
> - Consumer.addKeywordResult(Context, "continue");
> + Consumer.addKeywordResult("continue");
>
> - if (!getCurFunction()->SwitchStack.empty()) {
> - Consumer.addKeywordResult(Context, "case");
> - Consumer.addKeywordResult(Context, "default");
> + if (!SemaRef.getCurFunction()->SwitchStack.empty()) {
> + Consumer.addKeywordResult("case");
> + Consumer.addKeywordResult("default");
> }
> } else {
> - if (getLangOptions().CPlusPlus) {
> - Consumer.addKeywordResult(Context, "namespace");
> - Consumer.addKeywordResult(Context, "template");
> + if (SemaRef.getLangOptions().CPlusPlus) {
> + Consumer.addKeywordResult("namespace");
> + Consumer.addKeywordResult("template");
> }
>
> if (S && S->isClassScope()) {
> - Consumer.addKeywordResult(Context, "explicit");
> - Consumer.addKeywordResult(Context, "friend");
> - Consumer.addKeywordResult(Context, "mutable");
> - Consumer.addKeywordResult(Context, "private");
> - Consumer.addKeywordResult(Context, "protected");
> - Consumer.addKeywordResult(Context, "public");
> - Consumer.addKeywordResult(Context, "virtual");
> + Consumer.addKeywordResult("explicit");
> + Consumer.addKeywordResult("friend");
> + Consumer.addKeywordResult("mutable");
> + Consumer.addKeywordResult("private");
> + Consumer.addKeywordResult("protected");
> + Consumer.addKeywordResult("public");
> + Consumer.addKeywordResult("virtual");
> }
> }
>
> - if (getLangOptions().CPlusPlus) {
> - Consumer.addKeywordResult(Context, "using");
> + if (SemaRef.getLangOptions().CPlusPlus) {
> + Consumer.addKeywordResult("using");
> +
> + if (SemaRef.getLangOptions().CPlusPlus0x)
> + Consumer.addKeywordResult("static_assert");
> + }
> + }
> +}
> +
> +/// \brief Try to "correct" a typo in the source code by finding
> +/// visible declarations whose names are similar to the name that was
> +/// present in the source code.
> +///
> +/// \param TypoName the \c DeclarationNameInfo structure that contains
> +/// the name that was present in the source code along with its location.
> +///
> +/// \param LookupKind the name-lookup criteria used to search for the name.
> +///
> +/// \param S the scope in which name lookup occurs.
> +///
> +/// \param SS the nested-name-specifier that precedes the name we're
> +/// looking for, if present.
> +///
> +/// \param MemberContext if non-NULL, the context in which to look for
> +/// a member access expression.
> +///
> +/// \param EnteringContext whether we're entering the context described by
> +/// the nested-name-specifier SS.
> +///
> +/// \param CTC The context in which typo correction occurs, which impacts the
> +/// set of keywords permitted.
> +///
> +/// \param OPT when non-NULL, the search for visible declarations will
> +/// also walk the protocols in the qualified interfaces of \p OPT.
> +///
> +/// \returns a \c TypoCorrection containing the corrected name if the typo
> +/// along with information such as the \c NamedDecl where the corrected name
> +/// was declared, and any additional \c NestedNameSpecifier needed to access
> +/// it (C++ only). The \c TypoCorrection is empty if there is no correction.
> +TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
> + Sema::LookupNameKind LookupKind,
> + Scope *S, CXXScopeSpec *SS,
> + DeclContext *MemberContext,
> + bool EnteringContext,
> + CorrectTypoContext CTC,
> + const ObjCObjectPointerType *OPT) {
> + if (Diags.hasFatalErrorOccurred() || !getLangOptions().SpellChecking)
> + return TypoCorrection();
> +
> + // We only attempt to correct typos for identifiers.
> + IdentifierInfo *Typo = TypoName.getName().getAsIdentifierInfo();
> + if (!Typo)
> + return TypoCorrection();
>
> - if (getLangOptions().CPlusPlus0x)
> - Consumer.addKeywordResult(Context, "static_assert");
> + // If the scope specifier itself was invalid, don't try to correct
> + // typos.
> + if (SS && SS->isInvalid())
> + return TypoCorrection();
> +
> + // Never try to correct typos during template deduction or
> + // instantiation.
> + if (!ActiveTemplateInstantiations.empty())
> + return TypoCorrection();
> +
> + NamespaceSpecifierSet Namespaces(Context, CurContext);
> +
> + TypoCorrectionConsumer Consumer(*this, Typo);
> +
> + // Perform name lookup to find visible, similarly-named entities.
> + bool IsUnqualifiedLookup = false;
> + if (MemberContext) {
> + LookupVisibleDecls(MemberContext, LookupKind, Consumer);
> +
> + // Look in qualified interfaces.
> + if (OPT) {
> + for (ObjCObjectPointerType::qual_iterator
> + I = OPT->qual_begin(), E = OPT->qual_end();
> + I != E; ++I)
> + LookupVisibleDecls(*I, LookupKind, Consumer);
> + }
> + } else if (SS && SS->isSet()) {
> + DeclContext *DC = computeDeclContext(*SS, EnteringContext);
> + if (!DC)
> + return TypoCorrection();
> +
> + // Provide a stop gap for files that are just seriously broken. Trying
> + // to correct all typos can turn into a HUGE performance penalty, causing
> + // some files to take minutes to get rejected by the parser.
> + if (TyposCorrected + UnqualifiedTyposCorrected.size() >= 20)
> + return TypoCorrection();
> + ++TyposCorrected;
> +
> + LookupVisibleDecls(DC, LookupKind, Consumer);
> + } else {
> + IsUnqualifiedLookup = true;
> + UnqualifiedTyposCorrectedMap::iterator Cached
> + = UnqualifiedTyposCorrected.find(Typo);
> + if (Cached == UnqualifiedTyposCorrected.end()) {
> + // Provide a stop gap for files that are just seriously broken. Trying
> + // to correct all typos can turn into a HUGE performance penalty, causing
> + // some files to take minutes to get rejected by the parser.
> + if (TyposCorrected + UnqualifiedTyposCorrected.size() >= 20)
> + return TypoCorrection();
> +
> + // For unqualified lookup, look through all of the names that we have
> + // seen in this translation unit.
> + for (IdentifierTable::iterator I = Context.Idents.begin(),
> + IEnd = Context.Idents.end();
> + I != IEnd; ++I)
> + Consumer.FoundName(I->getKey());
> +
> + // Walk through identifiers in external identifier sources.
> + if (IdentifierInfoLookup *External
> + = Context.Idents.getExternalIdentifierLookup()) {
> + llvm::OwningPtr<IdentifierIterator> Iter(External->getIdentifiers());
> + do {
> + llvm::StringRef Name = Iter->Next();
> + if (Name.empty())
> + break;
> +
> + Consumer.FoundName(Name);
> + } while (true);
> + }
> + } else {
> + // Use the cached value, unless it's a keyword. In the keyword case, we'll
> + // end up adding the keyword below.
> + if (!Cached->second)
> + return TypoCorrection();
> +
> + if (!Cached->second.isKeyword())
> + Consumer.addCorrection(Cached->second);
> }
> }
>
> + AddKeywordsToConsumer(*this, Consumer, S, CTC);
> +
> // If we haven't found anything, we're done.
> if (Consumer.empty()) {
> // If this was an unqualified lookup, note that no correction was found.
> if (IsUnqualifiedLookup)
> (void)UnqualifiedTyposCorrected[Typo];
>
> - return DeclarationName();
> + return TypoCorrection();
> }
>
> // Make sure that the user typed at least 3 characters for each correction
> // made. Otherwise, we don't even both looking at the results.
> -
> - // We also suppress exact matches; those should be handled by a
> - // different mechanism (e.g., one that introduces qualification in
> - // C++).
> unsigned ED = Consumer.getBestEditDistance();
> if (ED > 0 && Typo->getName().size() / ED < 3) {
> // If this was an unqualified lookup, note that no correction was found.
> if (IsUnqualifiedLookup)
> (void)UnqualifiedTyposCorrected[Typo];
>
> - return DeclarationName();
> + return TypoCorrection();
> + }
> +
> + // Build the NestedNameSpecifiers for the KnownNamespaces
> + if (getLangOptions().CPlusPlus) {
> + // Load any externally-known namespaces.
> + if (ExternalSource && !LoadedExternalKnownNamespaces) {
> + llvm::SmallVector<NamespaceDecl *, 4> ExternalKnownNamespaces;
> + LoadedExternalKnownNamespaces = true;
> + ExternalSource->ReadKnownNamespaces(ExternalKnownNamespaces);
> + for (unsigned I = 0, N = ExternalKnownNamespaces.size(); I != N; ++I)
> + KnownNamespaces[ExternalKnownNamespaces[I]] = true;
> + }
> +
> + for (llvm::DenseMap<NamespaceDecl*, bool>::iterator
> + KNI = KnownNamespaces.begin(),
> + KNIEnd = KnownNamespaces.end();
> + KNI != KNIEnd; ++KNI)
> + Namespaces.AddNamespace(KNI->first);
> }
>
> // Weed out any names that could not be found by name lookup.
> - bool LastLookupWasAccepted = false;
> - for (TypoCorrectionConsumer::iterator I = Consumer.begin(),
> - IEnd = Consumer.end();
> - I != IEnd; /* Increment in loop. */) {
> - // Keywords are always found.
> - if (I->second) {
> - ++I;
> - continue;
> + llvm::SmallPtrSet<IdentifierInfo*, 16> QualifiedResults;
> + LookupResult TmpRes(*this, TypoName, LookupKind);
> + TmpRes.suppressDiagnostics();
> + while (!Consumer.empty()) {
> + TypoCorrectionConsumer::distance_iterator DI = Consumer.begin();
> + unsigned ED = DI->first;
> + for (TypoCorrectionConsumer::result_iterator I = DI->second.begin(),
> + IEnd = DI->second.end();
> + I != IEnd; /* Increment in loop. */) {
> + // If the item already has been looked up or is a keyword, keep it
> + if (I->second.isResolved()) {
> + ++I;
> + continue;
> + }
> +
> + // Perform name lookup on this name.
> + IdentifierInfo *Name = I->second.getCorrectionAsIdentifierInfo();
> + LookupPotentialTypoResult(*this, TmpRes, Name, S, SS, MemberContext,
> + EnteringContext, CTC);
> +
> + switch (TmpRes.getResultKind()) {
> + case LookupResult::NotFound:
> + case LookupResult::NotFoundInCurrentInstantiation:
> + QualifiedResults.insert(Name);
> + // We didn't find this name in our scope, or didn't like what we found;
> + // ignore it.
> + {
> + TypoCorrectionConsumer::result_iterator Next = I;
> + ++Next;
> + DI->second.erase(I);
> + I = Next;
> + }
> + break;
> +
> + case LookupResult::Ambiguous:
> + // We don't deal with ambiguities.
> + return TypoCorrection();
> +
> + case LookupResult::Found:
> + case LookupResult::FoundOverloaded:
> + case LookupResult::FoundUnresolvedValue:
> + I->second.setCorrectionDecl(TmpRes.getAsSingle<NamedDecl>());
> + ++I;
> + break;
> + }
> }
>
> - // Perform name lookup on this name.
> - IdentifierInfo *Name = &Context.Idents.get(I->getKey());
> - LookupPotentialTypoResult(*this, Res, Name, S, SS, MemberContext,
> - EnteringContext, CTC);
> -
> - switch (Res.getResultKind()) {
> - case LookupResult::NotFound:
> - case LookupResult::NotFoundInCurrentInstantiation:
> - case LookupResult::Ambiguous:
> - // We didn't find this name in our scope, or didn't like what we found;
> - // ignore it.
> - Res.suppressDiagnostics();
> - {
> - TypoCorrectionConsumer::iterator Next = I;
> - ++Next;
> - Consumer.erase(I);
> - I = Next;
> - }
> - LastLookupWasAccepted = false;
> - break;
> -
> - case LookupResult::Found:
> - case LookupResult::FoundOverloaded:
> - case LookupResult::FoundUnresolvedValue:
> - ++I;
> - LastLookupWasAccepted = true;
> + if (DI->second.empty())
> + Consumer.erase(DI);
> + else if (!getLangOptions().CPlusPlus || QualifiedResults.empty() || !ED)
> + // If there are results in the closest possible bucket, stop
> break;
> +
> + // Only perform the qualified lookups for C++
> + if (getLangOptions().CPlusPlus) {
> + TmpRes.suppressDiagnostics();
> + for (llvm::SmallPtrSet<IdentifierInfo*,
> + 16>::iterator QRI = QualifiedResults.begin(),
> + QRIEnd = QualifiedResults.end();
> + QRI != QRIEnd; ++QRI) {
> + for (NamespaceSpecifierSet::iterator NI = Namespaces.begin(),
> + NIEnd = Namespaces.end();
> + NI != NIEnd; ++NI) {
> + DeclContext *Ctx = NI->DeclCtx;
> + unsigned QualifiedED = ED + NI->EditDistance;
> +
> + // Stop searching once the namespaces are too far away to create
> + // acceptable corrections for this identifier (since the namespaces
> + // are sorted in ascending order by edit distance)
> + if (QualifiedED > Consumer.getMaxEditDistance()) break;
> +
> + TmpRes.clear();
> + TmpRes.setLookupName(*QRI);
> + if (!LookupQualifiedName(TmpRes, Ctx)) continue;
> +
> + switch (TmpRes.getResultKind()) {
> + case LookupResult::Found:
> + case LookupResult::FoundOverloaded:
> + case LookupResult::FoundUnresolvedValue:
> + Consumer.addName((*QRI)->getName(), TmpRes.getAsSingle<NamedDecl>(),
> + QualifiedED, NI->NameSpecifier);
> + break;
> + case LookupResult::NotFound:
> + case LookupResult::NotFoundInCurrentInstantiation:
> + case LookupResult::Ambiguous:
> + break;
> + }
> + }
> + }
> }
>
> - if (Res.isAmbiguous()) {
> - // We don't deal with ambiguities.
> - Res.suppressDiagnostics();
> - Res.clear();
> - return DeclarationName();
> + QualifiedResults.clear();
> + }
> +
> + // No corrections remain...
> + if (Consumer.empty()) return TypoCorrection();
> +
> + TypoResultsMap &BestResults = Consumer.begin()->second;
> + ED = Consumer.begin()->first;
> +
> + if (ED > 0 && Typo->getName().size() / ED < 3) {
> + // If this was an unqualified lookup, note that no correction was found.
> + if (IsUnqualifiedLookup)
> + (void)UnqualifiedTyposCorrected[Typo];
> +
> + return TypoCorrection();
> + }
> +
> + // If we have multiple possible corrections, eliminate the ones where we
> + // added namespace qualifiers to try to resolve the ambiguity (and to favor
> + // corrections without additional namespace qualifiers)
> + if (getLangOptions().CPlusPlus && BestResults.size() > 1) {
> + TypoCorrectionConsumer::distance_iterator DI = Consumer.begin();
> + for (TypoCorrectionConsumer::result_iterator I = DI->second.begin(),
> + IEnd = DI->second.end();
> + I != IEnd; /* Increment in loop. */) {
> + if (I->second.getCorrectionSpecifier() != NULL) {
> + TypoCorrectionConsumer::result_iterator Cur = I;
> + ++I;
> + DI->second.erase(Cur);
> + } else ++I;
> }
> }
>
> // If only a single name remains, return that result.
> - if (Consumer.size() == 1) {
> - IdentifierInfo *Name = &Context.Idents.get(Consumer.begin()->getKey());
> - if (Consumer.begin()->second) {
> - Res.suppressDiagnostics();
> - Res.clear();
> -
> - // Don't correct to a keyword that's the same as the typo; the keyword
> - // wasn't actually in scope.
> - if (ED == 0) {
> - Res.setLookupName(Typo);
> - return DeclarationName();
> - }
> + if (BestResults.size() == 1) {
> + const llvm::StringMapEntry<TypoCorrection> &Correction = *(BestResults.begin());
> + const TypoCorrection &Result = Correction.second;
>
> - } else if (!LastLookupWasAccepted) {
> - // Perform name lookup on this name.
> - LookupPotentialTypoResult(*this, Res, Name, S, SS, MemberContext,
> - EnteringContext, CTC);
> - }
> + // Don't correct to a keyword that's the same as the typo; the keyword
> + // wasn't actually in scope.
> + if (ED == 0 && Result.isKeyword()) return TypoCorrection();
>
> + assert(Result.isResolved() && "correction has not been looked up");
> // Record the correction for unqualified lookup.
> if (IsUnqualifiedLookup)
> - UnqualifiedTyposCorrected[Typo]
> - = std::make_pair(Name->getName(), Consumer.begin()->second);
> + UnqualifiedTyposCorrected[Typo] = Result;
>
> - return &Context.Idents.get(Consumer.begin()->getKey());
> + return Result;
> }
> - else if (Consumer.size() > 1 && CTC == CTC_ObjCMessageReceiver
> - && Consumer["super"]) {
> - // Prefix 'super' when we're completing in a message-receiver
> + else if (BestResults.size() > 1 && CTC == CTC_ObjCMessageReceiver
> + && BestResults["super"].isKeyword()) {
> + // Prefer 'super' when we're completing in a message-receiver
> // context.
> - Res.suppressDiagnostics();
> - Res.clear();
>
> // Don't correct to a keyword that's the same as the typo; the keyword
> // wasn't actually in scope.
> - if (ED == 0) {
> - Res.setLookupName(Typo);
> - return DeclarationName();
> - }
> + if (ED == 0) return TypoCorrection();
>
> // Record the correction for unqualified lookup.
> if (IsUnqualifiedLookup)
> - UnqualifiedTyposCorrected[Typo]
> - = std::make_pair("super", Consumer.begin()->second);
> + UnqualifiedTyposCorrected[Typo] = BestResults["super"];
>
> - return &Context.Idents.get("super");
> + return BestResults["super"];
> }
>
> - Res.suppressDiagnostics();
> - Res.setLookupName(Typo);
> - Res.clear();
> - // Record the correction for unqualified lookup.
> if (IsUnqualifiedLookup)
> (void)UnqualifiedTyposCorrected[Typo];
>
> - return DeclarationName();
> + return TypoCorrection();
> +}
> +
> +std::string TypoCorrection::getAsString(const LangOptions &LO) const {
> + if (CorrectionNameSpec) {
> + std::string tmpBuffer;
> + llvm::raw_string_ostream PrefixOStream(tmpBuffer);
> + CorrectionNameSpec->print(PrefixOStream, PrintingPolicy(LO));
> + return PrefixOStream.str() + CorrectionName.getAsString();
> + }
> +
> + return CorrectionName.getAsString();
> }
>
> Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=134007&r1=134006&r2=134007&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaTemplate.cpp Tue Jun 28 11:20:02 2011
> @@ -294,26 +294,31 @@
> 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);
> }
> }
>
> Modified: cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp?rev=134007&r1=134006&r2=134007&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp Tue Jun 28 11:20:02 2011
> @@ -716,17 +716,19 @@
>
> 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;
> }
> }
>
>
> Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=134007&r1=134006&r2=134007&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTReader.cpp Tue Jun 28 11:20:02 2011
> @@ -2369,6 +2369,15 @@
> 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 @@
> 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);
>
> Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=134007&r1=134006&r2=134007&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTWriter.cpp Tue Jun 28 11:20:02 2011
> @@ -781,6 +781,8 @@
> 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 @@
> 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 @@
> 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);
>
> Modified: cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4.cpp?rev=134007&r1=134006&r2=134007&view=diff
> ==============================================================================
> --- cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4.cpp (original)
> +++ cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4.cpp Tue Jun 28 11:20:02 2011
> @@ -19,8 +19,9 @@
> }
>
> 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 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();
>
> Modified: cfe/trunk/test/FixIt/typo.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/typo.cpp?rev=134007&r1=134006&r2=134007&view=diff
> ==============================================================================
> --- cfe/trunk/test/FixIt/typo.cpp (original)
> +++ cfe/trunk/test/FixIt/typo.cpp Tue Jun 28 11:20:02 2011
> @@ -74,3 +74,9 @@
> 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'?}}
>
> Added: cfe/trunk/test/PCH/Inputs/typo.hpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/Inputs/typo.hpp?rev=134007&view=auto
> ==============================================================================
> --- cfe/trunk/test/PCH/Inputs/typo.hpp (added)
> +++ cfe/trunk/test/PCH/Inputs/typo.hpp Tue Jun 28 11:20:02 2011
> @@ -0,0 +1,8 @@
> +namespace boost {
> + template<typename F> class function {};
> +
> + namespace graph {
> + template<typename V, typename E> class adjacency_list { };
> + };
> +}
> +
>
> Propchange: cfe/trunk/test/PCH/Inputs/typo.hpp
> ------------------------------------------------------------------------------
> svn:eol-style = native
>
> Propchange: cfe/trunk/test/PCH/Inputs/typo.hpp
> ------------------------------------------------------------------------------
> svn:keywords = Id
>
> Propchange: cfe/trunk/test/PCH/Inputs/typo.hpp
> ------------------------------------------------------------------------------
> svn:mime-type = text/plain
>
> Added: cfe/trunk/test/PCH/typo.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/typo.cpp?rev=134007&view=auto
> ==============================================================================
> --- cfe/trunk/test/PCH/typo.cpp (added)
> +++ cfe/trunk/test/PCH/typo.cpp Tue Jun 28 11:20:02 2011
> @@ -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
>
> Propchange: cfe/trunk/test/PCH/typo.cpp
> ------------------------------------------------------------------------------
> svn:eol-style = native
>
> Propchange: cfe/trunk/test/PCH/typo.cpp
> ------------------------------------------------------------------------------
> svn:keywords = Id
>
> Propchange: cfe/trunk/test/PCH/typo.cpp
> ------------------------------------------------------------------------------
> svn:mime-type = text/plain
>
> Added: cfe/trunk/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp?rev=134007&view=auto
> ==============================================================================
> --- cfe/trunk/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp (added)
> +++ cfe/trunk/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp Tue Jun 28 11:20:02 2011
> @@ -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'?}}
> +}
>
> Propchange: cfe/trunk/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp
> ------------------------------------------------------------------------------
> svn:eol-style = native
>
> Propchange: cfe/trunk/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp
> ------------------------------------------------------------------------------
> svn:keywords = Id
>
> Propchange: cfe/trunk/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp
> ------------------------------------------------------------------------------
> svn:mime-type = text/plain
>
> Modified: cfe/trunk/test/SemaObjC/ivar-ref-misuse.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/ivar-ref-misuse.m?rev=134007&r1=134006&r2=134007&view=diff
> ==============================================================================
> --- cfe/trunk/test/SemaObjC/ivar-ref-misuse.m (original)
> +++ cfe/trunk/test/SemaObjC/ivar-ref-misuse.m Tue Jun 28 11:20:02 2011
> @@ -1,6 +1,6 @@
> // RUN: %clang_cc1 -fsyntax-only -verify %s
>
> - at interface Sprite {
> + at interface Sprite { // expected-note{{'Sprite' declared here}}
> int sprite, spree;
> int UseGlobalBar;
> }
> @@ -17,7 +17,8 @@
> + (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 {
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20110628/6fdf398b/attachment.html>
More information about the cfe-commits
mailing list