[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/
Douglas Gregor
dgregor at apple.com
Tue Jun 28 13:04:28 PDT 2011
This was a real problem that I fixed in r134009.
- Doug
On Jun 28, 2011, at 1:03 PM, Chad Rosier wrote:
> Please disregard. Looks as if an overlapping failure is causing the problem.
>
> On Jun 28, 2011, at 12:36 PM, Chad Rosier wrote:
>
>> 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
>>
>> _______________________________________________
>> 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/ac450b84/attachment.html>
More information about the cfe-commits
mailing list