aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema
diff options
context:
space:
mode:
authorRoman Divacky <rdivacky@FreeBSD.org>2009-11-19 09:00:00 +0000
committerRoman Divacky <rdivacky@FreeBSD.org>2009-11-19 09:00:00 +0000
commitf5bd02d290ff15268853e0456c130a1afa15e907 (patch)
treec7f5a7b6fd212399d821b83b22c1e6a42e8c4a0d /lib/Sema
parentb3d5a323a5ca92ea73443499cee2f15db1ff0fb3 (diff)
downloadsrc-f5bd02d290ff15268853e0456c130a1afa15e907.tar.gz
src-f5bd02d290ff15268853e0456c130a1afa15e907.zip
Update clang to r89337.
Notes
Notes: svn path=/vendor/clang/dist/; revision=199512
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/CodeCompleteConsumer.cpp61
-rw-r--r--lib/Sema/Lookup.h86
-rw-r--r--lib/Sema/Sema.cpp2
-rw-r--r--lib/Sema/Sema.h66
-rw-r--r--lib/Sema/SemaCXXCast.cpp26
-rw-r--r--lib/Sema/SemaCodeComplete.cpp523
-rw-r--r--lib/Sema/SemaDecl.cpp457
-rw-r--r--lib/Sema/SemaDeclCXX.cpp22
-rw-r--r--lib/Sema/SemaDeclObjC.cpp7
-rw-r--r--lib/Sema/SemaExprCXX.cpp6
-rw-r--r--lib/Sema/SemaLookup.cpp6
-rw-r--r--lib/Sema/SemaOverload.cpp222
-rw-r--r--lib/Sema/SemaTemplate.cpp41
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp42
-rw-r--r--lib/Sema/TreeTransform.h23
15 files changed, 1175 insertions, 415 deletions
diff --git a/lib/Sema/CodeCompleteConsumer.cpp b/lib/Sema/CodeCompleteConsumer.cpp
index 88ac4e49cf9e..a9d83010576a 100644
--- a/lib/Sema/CodeCompleteConsumer.cpp
+++ b/lib/Sema/CodeCompleteConsumer.cpp
@@ -117,6 +117,33 @@ CodeCompletionString::Chunk::CreateCurrentParameter(
return Chunk(CK_CurrentParameter, CurrentParameter);
}
+CodeCompletionString::Chunk CodeCompletionString::Chunk::Clone() const {
+ switch (Kind) {
+ case CK_TypedText:
+ case CK_Text:
+ case CK_Placeholder:
+ case CK_Informative:
+ case CK_CurrentParameter:
+ case CK_LeftParen:
+ case CK_RightParen:
+ case CK_LeftBracket:
+ case CK_RightBracket:
+ case CK_LeftBrace:
+ case CK_RightBrace:
+ case CK_LeftAngle:
+ case CK_RightAngle:
+ case CK_Comma:
+ return Chunk(Kind, Text);
+
+ case CK_Optional: {
+ std::auto_ptr<CodeCompletionString> Opt(Optional->Clone());
+ return CreateOptional(Opt);
+ }
+ }
+
+ // Silence GCC warning.
+ return Chunk();
+}
void
CodeCompletionString::Chunk::Destroy() {
@@ -168,6 +195,20 @@ std::string CodeCompletionString::getAsString() const {
return Result;
}
+const char *CodeCompletionString::getTypedText() const {
+ for (iterator C = begin(), CEnd = end(); C != CEnd; ++C)
+ if (C->Kind == CK_TypedText)
+ return C->Text;
+
+ return 0;
+}
+
+CodeCompletionString *CodeCompletionString::Clone() const {
+ CodeCompletionString *Result = new CodeCompletionString;
+ for (iterator C = begin(), CEnd = end(); C != CEnd; ++C)
+ Result->AddChunk(C->Clone());
+ return Result;
+}
namespace {
// Escape a string for XML-like formatting.
@@ -473,6 +514,13 @@ CodeCompletionString *CodeCompletionString::Deserialize(llvm::StringRef &Str) {
return Result;
}
+void CodeCompleteConsumer::Result::Destroy() {
+ if (Kind == RK_Pattern) {
+ delete Pattern;
+ Pattern = 0;
+ }
+}
+
//===----------------------------------------------------------------------===//
// Code completion overload candidate implementation
//===----------------------------------------------------------------------===//
@@ -545,6 +593,12 @@ PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
OS << '\n';
break;
}
+
+ case Result::RK_Pattern: {
+ OS << "Pattern : " << Results[I].Rank << " : "
+ << Results[I].Pattern->getAsString() << '\n';
+ break;
+ }
}
}
@@ -627,6 +681,13 @@ CIndexCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
OS << '\n';
break;
}
+
+ case Result::RK_Pattern: {
+ OS << "Pattern:";
+ Results[I].Pattern->Serialize(OS);
+ OS << '\n';
+ break;
+ }
}
}
diff --git a/lib/Sema/Lookup.h b/lib/Sema/Lookup.h
index 6e72dcef161a..10cc818b8baa 100644
--- a/lib/Sema/Lookup.h
+++ b/lib/Sema/Lookup.h
@@ -201,6 +201,13 @@ public:
return getResultKind() == Ambiguous;
}
+ /// Determines if this names a single result which is not an
+ /// unresolved value using decl. If so, it is safe to call
+ /// getFoundDecl().
+ bool isSingleResult() const {
+ return getResultKind() == Found;
+ }
+
LookupResultKind getResultKind() const {
sanity();
return ResultKind;
@@ -248,12 +255,24 @@ public:
Decls.set_size(N);
}
- /// \brief Resolves the kind of the lookup, possibly hiding decls.
+ /// \brief Resolves the result kind of the lookup, possibly hiding
+ /// decls.
///
/// This should be called in any environment where lookup might
/// generate multiple lookup results.
void resolveKind();
+ /// \brief Re-resolves the result kind of the lookup after a set of
+ /// removals has been performed.
+ void resolveKindAfterFilter() {
+ if (Decls.empty())
+ ResultKind = NotFound;
+ else {
+ ResultKind = Found;
+ resolveKind();
+ }
+ }
+
/// \brief Fetch this as an unambiguous single declaration
/// (possibly an overloaded one).
///
@@ -272,6 +291,12 @@ public:
return Decls[0]->getUnderlyingDecl();
}
+ /// Fetches a representative decl. Useful for lazy diagnostics.
+ NamedDecl *getRepresentativeDecl() const {
+ assert(!Decls.empty() && "cannot get representative of empty set");
+ return Decls[0];
+ }
+
/// \brief Asks if the result is a single tag decl.
bool isSingleTagDecl() const {
return getResultKind() == Found && isa<TagDecl>(getFoundDecl());
@@ -337,6 +362,65 @@ public:
return NameLoc;
}
+ /// A class for iterating through a result set and possibly
+ /// filtering out results. The results returned are possibly
+ /// sugared.
+ class Filter {
+ LookupResult &Results;
+ unsigned I;
+ bool ErasedAny;
+#ifndef NDEBUG
+ bool CalledDone;
+#endif
+
+ friend class LookupResult;
+ Filter(LookupResult &Results)
+ : Results(Results), I(0), ErasedAny(false)
+#ifndef NDEBUG
+ , CalledDone(false)
+#endif
+ {}
+
+ public:
+#ifndef NDEBUG
+ ~Filter() {
+ assert(CalledDone &&
+ "LookupResult::Filter destroyed without done() call");
+ }
+#endif
+
+ bool hasNext() const {
+ return I != Results.Decls.size();
+ }
+
+ NamedDecl *next() {
+ assert(I < Results.Decls.size() && "next() called on empty filter");
+ return Results.Decls[I++];
+ }
+
+ /// Erase the last element returned from this iterator.
+ void erase() {
+ Results.Decls[--I] = Results.Decls.back();
+ Results.Decls.pop_back();
+ ErasedAny = true;
+ }
+
+ void done() {
+#ifndef NDEBUG
+ assert(!CalledDone && "done() called twice");
+ CalledDone = true;
+#endif
+
+ if (ErasedAny)
+ Results.resolveKindAfterFilter();
+ }
+ };
+
+ /// Create a filter for this result set.
+ Filter makeFilter() {
+ return Filter(*this);
+ }
+
private:
void diagnose() {
if (isAmbiguous())
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index b2bbac8bc2a9..fe2d7448b42f 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -319,7 +319,7 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
&Context.Idents.get("Protocol"),
SourceLocation(), true);
Context.setObjCProtoType(Context.getObjCInterfaceType(ProtocolDecl));
- PushOnScopeChains(ProtocolDecl, TUScope);
+ PushOnScopeChains(ProtocolDecl, TUScope, false);
}
// Create the built-in typedef for 'id'.
if (Context.getObjCIdType().isNull()) {
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 3e186b2b5be9..ad4c90bdc2a5 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -548,26 +548,32 @@ public:
DeclPtrTy HandleDeclarator(Scope *S, Declarator &D,
MultiTemplateParamsArg TemplateParameterLists,
bool IsFunctionDefinition);
- void RegisterLocallyScopedExternCDecl(NamedDecl *ND, NamedDecl *PrevDecl,
+ void RegisterLocallyScopedExternCDecl(NamedDecl *ND,
+ const LookupResult &Previous,
Scope *S);
void DiagnoseFunctionSpecifiers(Declarator& D);
+ bool CheckRedeclaration(DeclContext *DC,
+ DeclarationName Name,
+ SourceLocation NameLoc,
+ unsigned Diagnostic);
NamedDecl* ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
QualType R, DeclaratorInfo *DInfo,
- NamedDecl* PrevDecl, bool &Redeclaration);
+ LookupResult &Previous, bool &Redeclaration);
NamedDecl* ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
QualType R, DeclaratorInfo *DInfo,
- NamedDecl* PrevDecl,
+ LookupResult &Previous,
MultiTemplateParamsArg TemplateParamLists,
bool &Redeclaration);
- void CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl,
+ void CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous,
bool &Redeclaration);
NamedDecl* ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
QualType R, DeclaratorInfo *DInfo,
- NamedDecl* PrevDecl,
+ LookupResult &Previous,
MultiTemplateParamsArg TemplateParamLists,
bool IsFunctionDefinition,
bool &Redeclaration);
- void CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl,
+ void AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD);
+ void CheckFunctionDeclaration(FunctionDecl *NewFD, LookupResult &Previous,
bool IsExplicitSpecialization,
bool &Redeclaration,
bool &OverloadableAttrRequired);
@@ -779,15 +785,17 @@ public:
/// Subroutines of ActOnDeclarator().
TypedefDecl *ParseTypedefDecl(Scope *S, Declarator &D, QualType T,
DeclaratorInfo *DInfo);
- void MergeTypeDefDecl(TypedefDecl *New, Decl *Old);
+ void MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls);
bool MergeFunctionDecl(FunctionDecl *New, Decl *Old);
bool MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old);
- void MergeVarDecl(VarDecl *New, Decl *Old);
+ void MergeVarDecl(VarDecl *New, LookupResult &OldDecls);
bool MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old);
/// C++ Overloading.
- bool IsOverload(FunctionDecl *New, Decl* OldD,
- OverloadedFunctionDecl::function_iterator &MatchedDecl);
+ bool IsOverload(FunctionDecl *New, LookupResult &OldDecls,
+ NamedDecl *&OldDecl);
+ bool IsOverload(FunctionDecl *New, FunctionDecl *Old);
+
ImplicitConversionSequence
TryImplicitConversion(Expr* From, QualType ToType,
bool SuppressUserConversions,
@@ -822,7 +830,7 @@ public:
bool AllowConversionFunctions,
bool AllowExplicit, bool ForceRValue,
bool UserCast = false);
- bool DiagnoseAmbiguousUserDefinedConversion(Expr *From, QualType ToType);
+ bool DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType);
ImplicitConversionSequence::CompareKind
@@ -2324,8 +2332,8 @@ public:
const TemplateArgumentLoc *ExplicitTemplateArgs,
unsigned NumExplicitTemplateArgs,
SourceLocation RAngleLoc,
- NamedDecl *&PrevDecl);
- bool CheckMemberSpecialization(NamedDecl *Member, NamedDecl *&PrevDecl);
+ LookupResult &Previous);
+ bool CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous);
virtual DeclResult
ActOnExplicitInstantiation(Scope *S,
@@ -3638,14 +3646,38 @@ public:
virtual void CodeCompleteNamespaceAliasDecl(Scope *S);
virtual void CodeCompleteOperatorName(Scope *S);
- virtual void CodeCompleteObjCProperty(Scope *S, ObjCDeclSpec &ODS);
+ virtual void CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS);
+ virtual void CodeCompleteObjCPropertyGetter(Scope *S, DeclPtrTy ClassDecl,
+ DeclPtrTy *Methods,
+ unsigned NumMethods);
+ virtual void CodeCompleteObjCPropertySetter(Scope *S, DeclPtrTy ClassDecl,
+ DeclPtrTy *Methods,
+ unsigned NumMethods);
+
virtual void CodeCompleteObjCClassMessage(Scope *S, IdentifierInfo *FName,
- SourceLocation FNameLoc);
- virtual void CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver);
+ SourceLocation FNameLoc,
+ IdentifierInfo **SelIdents,
+ unsigned NumSelIdents);
+ virtual void CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver,
+ IdentifierInfo **SelIdents,
+ unsigned NumSelIdents);
virtual void CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
unsigned NumProtocols);
virtual void CodeCompleteObjCProtocolDecl(Scope *S);
- //@}
+ virtual void CodeCompleteObjCInterfaceDecl(Scope *S);
+ virtual void CodeCompleteObjCSuperclass(Scope *S,
+ IdentifierInfo *ClassName);
+ virtual void CodeCompleteObjCImplementationDecl(Scope *S);
+ virtual void CodeCompleteObjCInterfaceCategory(Scope *S,
+ IdentifierInfo *ClassName);
+ virtual void CodeCompleteObjCImplementationCategory(Scope *S,
+ IdentifierInfo *ClassName);
+ virtual void CodeCompleteObjCPropertyDefinition(Scope *S,
+ DeclPtrTy ObjCImpDecl);
+ virtual void CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
+ IdentifierInfo *PropertyName,
+ DeclPtrTy ObjCImpDecl);
+ //@}
//===--------------------------------------------------------------------===//
// Extra semantic analysis beyond the C type system
diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp
index e5ad338502df..6b4f87ef1dfb 100644
--- a/lib/Sema/SemaCXXCast.cpp
+++ b/lib/Sema/SemaCXXCast.cpp
@@ -175,6 +175,30 @@ Sema::ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
return ExprError();
}
+/// UnwrapDissimilarPointerTypes - Like Sema::UnwrapSimilarPointerTypes,
+/// this removes one level of indirection from both types, provided that they're
+/// the same kind of pointer (plain or to-member). Unlike the Sema function,
+/// this one doesn't care if the two pointers-to-member don't point into the
+/// same class. This is because CastsAwayConstness doesn't care.
+bool UnwrapDissimilarPointerTypes(QualType& T1, QualType& T2) {
+ const PointerType *T1PtrType = T1->getAs<PointerType>(),
+ *T2PtrType = T2->getAs<PointerType>();
+ if (T1PtrType && T2PtrType) {
+ T1 = T1PtrType->getPointeeType();
+ T2 = T2PtrType->getPointeeType();
+ return true;
+ }
+
+ const MemberPointerType *T1MPType = T1->getAs<MemberPointerType>(),
+ *T2MPType = T2->getAs<MemberPointerType>();
+ if (T1MPType && T2MPType) {
+ T1 = T1MPType->getPointeeType();
+ T2 = T2MPType->getPointeeType();
+ return true;
+ }
+ return false;
+}
+
/// CastsAwayConstness - Check if the pointer conversion from SrcType to
/// DestType casts away constness as defined in C++ 5.2.11p8ff. This is used by
/// the cast checkers. Both arguments must denote pointer (possibly to member)
@@ -195,7 +219,7 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType) {
llvm::SmallVector<Qualifiers, 8> cv1, cv2;
// Find the qualifications.
- while (Self.UnwrapSimilarPointerTypes(UnwrappedSrcType, UnwrappedDestType)) {
+ while (UnwrapDissimilarPointerTypes(UnwrappedSrcType, UnwrappedDestType)) {
cv1.push_back(UnwrappedSrcType.getQualifiers());
cv2.push_back(UnwrappedDestType.getQualifiers());
}
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index 9cecdadc867e..6dbb4426c20c 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -944,26 +944,50 @@ CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) {
return Result;
}
- Result->AddTypedTextChunk(
- Sel.getIdentifierInfoForSlot(0)->getName().str() + std::string(":"));
+ std::string SelName = Sel.getIdentifierInfoForSlot(0)->getName().str();
+ SelName += ':';
+ if (StartParameter == 0)
+ Result->AddTypedTextChunk(SelName);
+ else {
+ Result->AddInformativeChunk(SelName);
+
+ // If there is only one parameter, and we're past it, add an empty
+ // typed-text chunk since there is nothing to type.
+ if (Method->param_size() == 1)
+ Result->AddTypedTextChunk("");
+ }
unsigned Idx = 0;
for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
PEnd = Method->param_end();
P != PEnd; (void)++P, ++Idx) {
if (Idx > 0) {
- std::string Keyword = " ";
+ std::string Keyword;
+ if (Idx > StartParameter)
+ Keyword = " ";
if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
Keyword += II->getName().str();
Keyword += ":";
- Result->AddTextChunk(Keyword);
+ if (Idx < StartParameter || AllParametersAreInformative) {
+ Result->AddInformativeChunk(Keyword);
+ } else if (Idx == StartParameter)
+ Result->AddTypedTextChunk(Keyword);
+ else
+ Result->AddTextChunk(Keyword);
}
+
+ // If we're before the starting parameter, skip the placeholder.
+ if (Idx < StartParameter)
+ continue;
std::string Arg;
(*P)->getType().getAsStringInternal(Arg, S.Context.PrintingPolicy);
Arg = "(" + Arg + ")";
if (IdentifierInfo *II = (*P)->getIdentifier())
Arg += II->getName().str();
- Result->AddPlaceholderChunk(Arg);
+ if (AllParametersAreInformative)
+ Result->AddInformativeChunk(Arg);
+ else
+ Result->AddPlaceholderChunk(Arg);
}
return Result;
@@ -1066,6 +1090,17 @@ namespace {
else if (X.Rank > Y.Rank)
return false;
+ // We use a special ordering for keywords and patterns, based on the
+ // typed text.
+ if ((X.Kind == Result::RK_Keyword || X.Kind == Result::RK_Pattern) &&
+ (Y.Kind == Result::RK_Keyword || Y.Kind == Result::RK_Pattern)) {
+ const char *XStr = (X.Kind == Result::RK_Keyword)? X.Keyword
+ : X.Pattern->getTypedText();
+ const char *YStr = (Y.Kind == Result::RK_Keyword)? Y.Keyword
+ : Y.Pattern->getTypedText();
+ return strcmp(XStr, YStr) < 0;
+ }
+
// Result kinds are ordered by decreasing importance.
if (X.Kind < Y.Kind)
return true;
@@ -1087,12 +1122,14 @@ namespace {
return isEarlierDeclarationName(X.Declaration->getDeclName(),
Y.Declaration->getDeclName());
- case Result::RK_Keyword:
- return strcmp(X.Keyword, Y.Keyword) < 0;
-
case Result::RK_Macro:
return llvm::LowercaseString(X.Macro->getName()) <
llvm::LowercaseString(Y.Macro->getName());
+
+ case Result::RK_Keyword:
+ case Result::RK_Pattern:
+ llvm::llvm_unreachable("Result kinds handled above");
+ break;
}
// Silence GCC warning.
@@ -1120,6 +1157,9 @@ static void HandleCodeCompleteResults(Sema *S,
if (CodeCompleter)
CodeCompleter->ProcessCodeCompleteResults(*S, Results, NumResults);
+
+ for (unsigned I = 0; I != NumResults; ++I)
+ Results[I].Destroy();
}
void Sema::CodeCompleteOrdinaryName(Scope *S) {
@@ -1132,6 +1172,7 @@ void Sema::CodeCompleteOrdinaryName(Scope *S) {
}
static void AddObjCProperties(ObjCContainerDecl *Container,
+ bool AllowCategories,
DeclContext *CurContext,
ResultBuilder &Results) {
typedef CodeCompleteConsumer::Result Result;
@@ -1148,29 +1189,32 @@ static void AddObjCProperties(ObjCContainerDecl *Container,
for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(),
PEnd = Protocol->protocol_end();
P != PEnd; ++P)
- AddObjCProperties(*P, CurContext, Results);
+ AddObjCProperties(*P, AllowCategories, CurContext, Results);
} else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
- // Look through categories.
- for (ObjCCategoryDecl *Category = IFace->getCategoryList();
- Category; Category = Category->getNextClassCategory())
- AddObjCProperties(Category, CurContext, Results);
+ if (AllowCategories) {
+ // Look through categories.
+ for (ObjCCategoryDecl *Category = IFace->getCategoryList();
+ Category; Category = Category->getNextClassCategory())
+ AddObjCProperties(Category, AllowCategories, CurContext, Results);
+ }
// Look through protocols.
for (ObjCInterfaceDecl::protocol_iterator I = IFace->protocol_begin(),
E = IFace->protocol_end();
I != E; ++I)
- AddObjCProperties(*I, CurContext, Results);
+ AddObjCProperties(*I, AllowCategories, CurContext, Results);
// Look in the superclass.
if (IFace->getSuperClass())
- AddObjCProperties(IFace->getSuperClass(), CurContext, Results);
+ AddObjCProperties(IFace->getSuperClass(), AllowCategories, CurContext,
+ Results);
} else if (const ObjCCategoryDecl *Category
= dyn_cast<ObjCCategoryDecl>(Container)) {
// Look through protocols.
for (ObjCInterfaceDecl::protocol_iterator P = Category->protocol_begin(),
PEnd = Category->protocol_end();
P != PEnd; ++P)
- AddObjCProperties(*P, CurContext, Results);
+ AddObjCProperties(*P, AllowCategories, CurContext, Results);
}
}
@@ -1234,13 +1278,13 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *BaseE,
const ObjCObjectPointerType *ObjCPtr
= BaseType->getAsObjCInterfacePointerType();
assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
- AddObjCProperties(ObjCPtr->getInterfaceDecl(), CurContext, Results);
+ AddObjCProperties(ObjCPtr->getInterfaceDecl(), true, CurContext, Results);
// Add properties from the protocols in a qualified interface.
for (ObjCObjectPointerType::qual_iterator I = ObjCPtr->qual_begin(),
E = ObjCPtr->qual_end();
I != E; ++I)
- AddObjCProperties(*I, CurContext, Results);
+ AddObjCProperties(*I, true, CurContext, Results);
// FIXME: We could (should?) also look for "implicit" properties, identified
// only by the presence of nullary and unary selectors.
@@ -1611,34 +1655,104 @@ void Sema::CodeCompleteOperatorName(Scope *S) {
HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
}
-void Sema::CodeCompleteObjCProperty(Scope *S, ObjCDeclSpec &ODS) {
+/// \brief Determine whether the addition of the given flag to an Objective-C
+/// property's attributes will cause a conflict.
+static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
+ // Check if we've already added this flag.
+ if (Attributes & NewFlag)
+ return true;
+
+ Attributes |= NewFlag;
+
+ // Check for collisions with "readonly".
+ if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
+ (Attributes & (ObjCDeclSpec::DQ_PR_readwrite |
+ ObjCDeclSpec::DQ_PR_assign |
+ ObjCDeclSpec::DQ_PR_copy |
+ ObjCDeclSpec::DQ_PR_retain)))
+ return true;
+
+ // Check for more than one of { assign, copy, retain }.
+ unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign |
+ ObjCDeclSpec::DQ_PR_copy |
+ ObjCDeclSpec::DQ_PR_retain);
+ if (AssignCopyRetMask &&
+ AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
+ AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
+ AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain)
+ return true;
+
+ return false;
+}
+
+void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
if (!CodeCompleter)
return;
+
unsigned Attributes = ODS.getPropertyAttributes();
typedef CodeCompleteConsumer::Result Result;
ResultBuilder Results(*this);
Results.EnterNewScope();
- if (!(Attributes & ObjCDeclSpec::DQ_PR_readonly))
+ if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
Results.MaybeAddResult(CodeCompleteConsumer::Result("readonly", 0));
- if (!(Attributes & ObjCDeclSpec::DQ_PR_assign))
+ if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
Results.MaybeAddResult(CodeCompleteConsumer::Result("assign", 0));
- if (!(Attributes & ObjCDeclSpec::DQ_PR_readwrite))
+ if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
Results.MaybeAddResult(CodeCompleteConsumer::Result("readwrite", 0));
- if (!(Attributes & ObjCDeclSpec::DQ_PR_retain))
+ if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
Results.MaybeAddResult(CodeCompleteConsumer::Result("retain", 0));
- if (!(Attributes & ObjCDeclSpec::DQ_PR_copy))
+ if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
Results.MaybeAddResult(CodeCompleteConsumer::Result("copy", 0));
- if (!(Attributes & ObjCDeclSpec::DQ_PR_nonatomic))
+ if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
Results.MaybeAddResult(CodeCompleteConsumer::Result("nonatomic", 0));
- if (!(Attributes & ObjCDeclSpec::DQ_PR_setter))
- Results.MaybeAddResult(CodeCompleteConsumer::Result("setter", 0));
- if (!(Attributes & ObjCDeclSpec::DQ_PR_getter))
- Results.MaybeAddResult(CodeCompleteConsumer::Result("getter", 0));
+ if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
+ CodeCompletionString *Setter = new CodeCompletionString;
+ Setter->AddTypedTextChunk("setter");
+ Setter->AddTextChunk(" = ");
+ Setter->AddPlaceholderChunk("method");
+ Results.MaybeAddResult(CodeCompleteConsumer::Result(Setter, 0));
+ }
+ if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
+ CodeCompletionString *Getter = new CodeCompletionString;
+ Getter->AddTypedTextChunk("getter");
+ Getter->AddTextChunk(" = ");
+ Getter->AddPlaceholderChunk("method");
+ Results.MaybeAddResult(CodeCompleteConsumer::Result(Getter, 0));
+ }
Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
}
+/// \brief Descripts the kind of Objective-C method that we want to find
+/// via code completion.
+enum ObjCMethodKind {
+ MK_Any, //< Any kind of method, provided it means other specified criteria.
+ MK_ZeroArgSelector, //< Zero-argument (unary) selector.
+ MK_OneArgSelector //< One-argument selector.
+};
+
+static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
+ ObjCMethodKind WantKind,
+ IdentifierInfo **SelIdents,
+ unsigned NumSelIdents) {
+ Selector Sel = Method->getSelector();
+ if (NumSelIdents > Sel.getNumArgs())
+ return false;
+
+ switch (WantKind) {
+ case MK_Any: break;
+ case MK_ZeroArgSelector: return Sel.isUnarySelector();
+ case MK_OneArgSelector: return Sel.getNumArgs() == 1;
+ }
+
+ for (unsigned I = 0; I != NumSelIdents; ++I)
+ if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
+ return false;
+
+ return true;
+}
+
/// \brief Add all of the Objective-C methods in the given Objective-C
/// container to the set of results.
///
@@ -1658,14 +1772,26 @@ void Sema::CodeCompleteObjCProperty(Scope *S, ObjCDeclSpec &ODS) {
/// \param Results the structure into which we'll add results.
static void AddObjCMethods(ObjCContainerDecl *Container,
bool WantInstanceMethods,
+ ObjCMethodKind WantKind,
+ IdentifierInfo **SelIdents,
+ unsigned NumSelIdents,
DeclContext *CurContext,
ResultBuilder &Results) {
typedef CodeCompleteConsumer::Result Result;
for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
MEnd = Container->meth_end();
M != MEnd; ++M) {
- if ((*M)->isInstanceMethod() == WantInstanceMethods)
- Results.MaybeAddResult(Result(*M, 0), CurContext);
+ if ((*M)->isInstanceMethod() == WantInstanceMethods) {
+ // Check whether the selector identifiers we've been given are a
+ // subset of the identifiers for this particular method.
+ if (!isAcceptableObjCMethod(*M, WantKind, SelIdents, NumSelIdents))
+ continue;
+
+ Result R = Result(*M, 0);
+ R.StartParameter = NumSelIdents;
+ R.AllParametersAreInformative = (WantKind != MK_Any);
+ Results.MaybeAddResult(R, CurContext);
+ }
}
ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
@@ -1677,12 +1803,14 @@ static void AddObjCMethods(ObjCContainerDecl *Container,
for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
E = Protocols.end();
I != E; ++I)
- AddObjCMethods(*I, WantInstanceMethods, CurContext, Results);
+ AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents,
+ CurContext, Results);
// Add methods in categories.
for (ObjCCategoryDecl *CatDecl = IFace->getCategoryList(); CatDecl;
CatDecl = CatDecl->getNextClassCategory()) {
- AddObjCMethods(CatDecl, WantInstanceMethods, CurContext, Results);
+ AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
+ NumSelIdents, CurContext, Results);
// Add a categories protocol methods.
const ObjCList<ObjCProtocolDecl> &Protocols
@@ -1690,25 +1818,110 @@ static void AddObjCMethods(ObjCContainerDecl *Container,
for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
E = Protocols.end();
I != E; ++I)
- AddObjCMethods(*I, WantInstanceMethods, CurContext, Results);
+ AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
+ NumSelIdents, CurContext, Results);
// Add methods in category implementations.
if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
- AddObjCMethods(Impl, WantInstanceMethods, CurContext, Results);
+ AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
+ NumSelIdents, CurContext, Results);
}
// Add methods in superclass.
if (IFace->getSuperClass())
- AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, CurContext,
- Results);
+ AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
+ SelIdents, NumSelIdents, CurContext, Results);
// Add methods in our implementation, if any.
if (ObjCImplementationDecl *Impl = IFace->getImplementation())
- AddObjCMethods(Impl, WantInstanceMethods, CurContext, Results);
+ AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
+ NumSelIdents, CurContext, Results);
+}
+
+
+void Sema::CodeCompleteObjCPropertyGetter(Scope *S, DeclPtrTy ClassDecl,
+ DeclPtrTy *Methods,
+ unsigned NumMethods) {
+ typedef CodeCompleteConsumer::Result Result;
+
+ // Try to find the interface where getters might live.
+ ObjCInterfaceDecl *Class
+ = dyn_cast_or_null<ObjCInterfaceDecl>(ClassDecl.getAs<Decl>());
+ if (!Class) {
+ if (ObjCCategoryDecl *Category
+ = dyn_cast_or_null<ObjCCategoryDecl>(ClassDecl.getAs<Decl>()))
+ Class = Category->getClassInterface();
+
+ if (!Class)
+ return;
+ }
+
+ // Find all of the potential getters.
+ ResultBuilder Results(*this);
+ Results.EnterNewScope();
+
+ // FIXME: We need to do this because Objective-C methods don't get
+ // pushed into DeclContexts early enough. Argh!
+ for (unsigned I = 0; I != NumMethods; ++I) {
+ if (ObjCMethodDecl *Method
+ = dyn_cast_or_null<ObjCMethodDecl>(Methods[I].getAs<Decl>()))
+ if (Method->isInstanceMethod() &&
+ isAcceptableObjCMethod(Method, MK_ZeroArgSelector, 0, 0)) {
+ Result R = Result(Method, 0);
+ R.AllParametersAreInformative = true;
+ Results.MaybeAddResult(R, CurContext);
+ }
+ }
+
+ AddObjCMethods(Class, true, MK_ZeroArgSelector, 0, 0, CurContext, Results);
+ Results.ExitScope();
+ HandleCodeCompleteResults(this, CodeCompleter,Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteObjCPropertySetter(Scope *S, DeclPtrTy ObjCImplDecl,
+ DeclPtrTy *Methods,
+ unsigned NumMethods) {
+ typedef CodeCompleteConsumer::Result Result;
+
+ // Try to find the interface where setters might live.
+ ObjCInterfaceDecl *Class
+ = dyn_cast_or_null<ObjCInterfaceDecl>(ObjCImplDecl.getAs<Decl>());
+ if (!Class) {
+ if (ObjCCategoryDecl *Category
+ = dyn_cast_or_null<ObjCCategoryDecl>(ObjCImplDecl.getAs<Decl>()))
+ Class = Category->getClassInterface();
+
+ if (!Class)
+ return;
+ }
+
+ // Find all of the potential getters.
+ ResultBuilder Results(*this);
+ Results.EnterNewScope();
+
+ // FIXME: We need to do this because Objective-C methods don't get
+ // pushed into DeclContexts early enough. Argh!
+ for (unsigned I = 0; I != NumMethods; ++I) {
+ if (ObjCMethodDecl *Method
+ = dyn_cast_or_null<ObjCMethodDecl>(Methods[I].getAs<Decl>()))
+ if (Method->isInstanceMethod() &&
+ isAcceptableObjCMethod(Method, MK_OneArgSelector, 0, 0)) {
+ Result R = Result(Method, 0);
+ R.AllParametersAreInformative = true;
+ Results.MaybeAddResult(R, CurContext);
+ }
+ }
+
+ AddObjCMethods(Class, true, MK_OneArgSelector, 0, 0, CurContext, Results);
+
+ Results.ExitScope();
+ HandleCodeCompleteResults(this, CodeCompleter,Results.data(),Results.size());
}
void Sema::CodeCompleteObjCClassMessage(Scope *S, IdentifierInfo *FName,
- SourceLocation FNameLoc) {
+ SourceLocation FNameLoc,
+ IdentifierInfo **SelIdents,
+ unsigned NumSelIdents) {
typedef CodeCompleteConsumer::Result Result;
ObjCInterfaceDecl *CDecl = 0;
@@ -1734,7 +1947,8 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, IdentifierInfo *FName,
SuperTy = Context.getObjCObjectPointerType(SuperTy);
OwningExprResult Super
= Owned(new (Context) ObjCSuperExpr(FNameLoc, SuperTy));
- return CodeCompleteObjCInstanceMessage(S, (Expr *)Super.get());
+ return CodeCompleteObjCInstanceMessage(S, (Expr *)Super.get(),
+ SelIdents, NumSelIdents);
}
// Okay, we're calling a factory method in our superclass.
@@ -1756,21 +1970,25 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, IdentifierInfo *FName,
// probably calling an instance method.
OwningExprResult Super = ActOnDeclarationNameExpr(S, FNameLoc, FName,
false, 0, false);
- return CodeCompleteObjCInstanceMessage(S, (Expr *)Super.get());
+ return CodeCompleteObjCInstanceMessage(S, (Expr *)Super.get(),
+ SelIdents, NumSelIdents);
}
// Add all of the factory methods in this Objective-C class, its protocols,
// superclasses, categories, implementation, etc.
ResultBuilder Results(*this);
Results.EnterNewScope();
- AddObjCMethods(CDecl, false, CurContext, Results);
+ AddObjCMethods(CDecl, false, MK_Any, SelIdents, NumSelIdents, CurContext,
+ Results);
Results.ExitScope();
// This also suppresses remaining diagnostics.
HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
}
-void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver) {
+void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver,
+ IdentifierInfo **SelIdents,
+ unsigned NumSelIdents) {
typedef CodeCompleteConsumer::Result Result;
Expr *RecExpr = static_cast<Expr *>(Receiver);
@@ -1798,7 +2016,8 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver) {
ReceiverType->isObjCQualifiedClassType()) {
if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
- AddObjCMethods(ClassDecl, false, CurContext, Results);
+ AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, NumSelIdents,
+ CurContext, Results);
}
}
// Handle messages to a qualified ID ("id<foo>").
@@ -1808,19 +2027,22 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver) {
for (ObjCObjectPointerType::qual_iterator I = QualID->qual_begin(),
E = QualID->qual_end();
I != E; ++I)
- AddObjCMethods(*I, true, CurContext, Results);
+ AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
+ Results);
}
// Handle messages to a pointer to interface type.
else if (const ObjCObjectPointerType *IFacePtr
= ReceiverType->getAsObjCInterfacePointerType()) {
// Search the class, its superclasses, etc., for instance methods.
- AddObjCMethods(IFacePtr->getInterfaceDecl(), true, CurContext, Results);
+ AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
+ NumSelIdents, CurContext, Results);
// Search protocols for instance methods.
for (ObjCObjectPointerType::qual_iterator I = IFacePtr->qual_begin(),
E = IFacePtr->qual_end();
I != E; ++I)
- AddObjCMethods(*I, true, CurContext, Results);
+ AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
+ Results);
}
Results.ExitScope();
@@ -1885,3 +2107,210 @@ void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
}
+
+/// \brief Add all of the Objective-C interface declarations that we find in
+/// the given (translation unit) context.
+static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
+ bool OnlyForwardDeclarations,
+ bool OnlyUnimplemented,
+ ResultBuilder &Results) {
+ typedef CodeCompleteConsumer::Result Result;
+
+ for (DeclContext::decl_iterator D = Ctx->decls_begin(),
+ DEnd = Ctx->decls_end();
+ D != DEnd; ++D) {
+ // Record any interfaces we find.
+ if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D))
+ if ((!OnlyForwardDeclarations || Class->isForwardDecl()) &&
+ (!OnlyUnimplemented || !Class->getImplementation()))
+ Results.MaybeAddResult(Result(Class, 0), CurContext);
+
+ // Record any forward-declared interfaces we find.
+ if (ObjCClassDecl *Forward = dyn_cast<ObjCClassDecl>(*D)) {
+ for (ObjCClassDecl::iterator C = Forward->begin(), CEnd = Forward->end();
+ C != CEnd; ++C)
+ if ((!OnlyForwardDeclarations || C->getInterface()->isForwardDecl()) &&
+ (!OnlyUnimplemented || !C->getInterface()->getImplementation()))
+ Results.MaybeAddResult(Result(C->getInterface(), 0), CurContext);
+ }
+ }
+}
+
+void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
+ ResultBuilder Results(*this);
+ Results.EnterNewScope();
+
+ // Add all classes.
+ AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, true,
+ false, Results);
+
+ Results.ExitScope();
+ HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName) {
+ ResultBuilder Results(*this);
+ Results.EnterNewScope();
+
+ // Make sure that we ignore the class we're currently defining.
+ NamedDecl *CurClass
+ = LookupSingleName(TUScope, ClassName, LookupOrdinaryName);
+ if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
+ Results.Ignore(CurClass);
+
+ // Add all classes.
+ AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
+ false, Results);
+
+ Results.ExitScope();
+ HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
+ ResultBuilder Results(*this);
+ Results.EnterNewScope();
+
+ // Add all unimplemented classes.
+ AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
+ true, Results);
+
+ Results.ExitScope();
+ HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
+ IdentifierInfo *ClassName) {
+ typedef CodeCompleteConsumer::Result Result;
+
+ ResultBuilder Results(*this);
+
+ // Ignore any categories we find that have already been implemented by this
+ // interface.
+ llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
+ NamedDecl *CurClass
+ = LookupSingleName(TUScope, ClassName, LookupOrdinaryName);
+ if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass))
+ for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
+ Category = Category->getNextClassCategory())
+ CategoryNames.insert(Category->getIdentifier());
+
+ // Add all of the categories we know about.
+ Results.EnterNewScope();
+ TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
+ for (DeclContext::decl_iterator D = TU->decls_begin(),
+ DEnd = TU->decls_end();
+ D != DEnd; ++D)
+ if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(*D))
+ if (CategoryNames.insert(Category->getIdentifier()))
+ Results.MaybeAddResult(Result(Category, 0), CurContext);
+ Results.ExitScope();
+
+ HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
+ IdentifierInfo *ClassName) {
+ typedef CodeCompleteConsumer::Result Result;
+
+ // Find the corresponding interface. If we couldn't find the interface, the
+ // program itself is ill-formed. However, we'll try to be helpful still by
+ // providing the list of all of the categories we know about.
+ NamedDecl *CurClass
+ = LookupSingleName(TUScope, ClassName, LookupOrdinaryName);
+ ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
+ if (!Class)
+ return CodeCompleteObjCInterfaceCategory(S, ClassName);
+
+ ResultBuilder Results(*this);
+
+ // Add all of the categories that have have corresponding interface
+ // declarations in this class and any of its superclasses, except for
+ // already-implemented categories in the class itself.
+ llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
+ Results.EnterNewScope();
+ bool IgnoreImplemented = true;
+ while (Class) {
+ for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
+ Category = Category->getNextClassCategory())
+ if ((!IgnoreImplemented || !Category->getImplementation()) &&
+ CategoryNames.insert(Category->getIdentifier()))
+ Results.MaybeAddResult(Result(Category, 0), CurContext);
+
+ Class = Class->getSuperClass();
+ IgnoreImplemented = false;
+ }
+ Results.ExitScope();
+
+ HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteObjCPropertyDefinition(Scope *S, DeclPtrTy ObjCImpDecl) {
+ typedef CodeCompleteConsumer::Result Result;
+ ResultBuilder Results(*this);
+
+ // Figure out where this @synthesize lives.
+ ObjCContainerDecl *Container
+ = dyn_cast_or_null<ObjCContainerDecl>(ObjCImpDecl.getAs<Decl>());
+ if (!Container ||
+ (!isa<ObjCImplementationDecl>(Container) &&
+ !isa<ObjCCategoryImplDecl>(Container)))
+ return;
+
+ // Ignore any properties that have already been implemented.
+ for (DeclContext::decl_iterator D = Container->decls_begin(),
+ DEnd = Container->decls_end();
+ D != DEnd; ++D)
+ if (ObjCPropertyImplDecl *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(*D))
+ Results.Ignore(PropertyImpl->getPropertyDecl());
+
+ // Add any properties that we find.
+ Results.EnterNewScope();
+ if (ObjCImplementationDecl *ClassImpl
+ = dyn_cast<ObjCImplementationDecl>(Container))
+ AddObjCProperties(ClassImpl->getClassInterface(), false, CurContext,
+ Results);
+ else
+ AddObjCProperties(cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
+ false, CurContext, Results);
+ Results.ExitScope();
+
+ HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
+ IdentifierInfo *PropertyName,
+ DeclPtrTy ObjCImpDecl) {
+ typedef CodeCompleteConsumer::Result Result;
+ ResultBuilder Results(*this);
+
+ // Figure out where this @synthesize lives.
+ ObjCContainerDecl *Container
+ = dyn_cast_or_null<ObjCContainerDecl>(ObjCImpDecl.getAs<Decl>());
+ if (!Container ||
+ (!isa<ObjCImplementationDecl>(Container) &&
+ !isa<ObjCCategoryImplDecl>(Container)))
+ return;
+
+ // Figure out which interface we're looking into.
+ ObjCInterfaceDecl *Class = 0;
+ if (ObjCImplementationDecl *ClassImpl
+ = dyn_cast<ObjCImplementationDecl>(Container))
+ Class = ClassImpl->getClassInterface();
+ else
+ Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl()
+ ->getClassInterface();
+
+ // Add all of the instance variables in this class and its superclasses.
+ Results.EnterNewScope();
+ for(; Class; Class = Class->getSuperClass()) {
+ // FIXME: We could screen the type of each ivar for compatibility with
+ // the property, but is that being too paternal?
+ for (ObjCInterfaceDecl::ivar_iterator IVar = Class->ivar_begin(),
+ IVarEnd = Class->ivar_end();
+ IVar != IVarEnd; ++IVar)
+ Results.MaybeAddResult(Result(*IVar, 0), CurContext);
+ }
+ Results.ExitScope();
+
+ HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+}
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 57c101bd32ce..b5109f825e57 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -311,14 +311,16 @@ void Sema::ExitDeclaratorContext(Scope *S) {
/// extension, in C when the previous function is already an
/// overloaded function declaration or has the "overloadable"
/// attribute.
-static bool AllowOverloadingOfFunction(Decl *PrevDecl, ASTContext &Context) {
+static bool AllowOverloadingOfFunction(LookupResult &Previous,
+ ASTContext &Context) {
if (Context.getLangOptions().CPlusPlus)
return true;
- if (isa<OverloadedFunctionDecl>(PrevDecl))
+ if (Previous.getResultKind() == LookupResult::FoundOverloaded)
return true;
- return PrevDecl->getAttr<OverloadableAttr>() != 0;
+ return (Previous.getResultKind() == LookupResult::Found
+ && Previous.getFoundDecl()->hasAttr<OverloadableAttr>());
}
/// Add this decl to the scope shadowed decl chains.
@@ -396,6 +398,48 @@ bool Sema::isDeclInScope(NamedDecl *&D, DeclContext *Ctx, Scope *S) {
return IdResolver.isDeclInScope(D, Ctx, Context, S);
}
+static bool isOutOfScopePreviousDeclaration(NamedDecl *,
+ DeclContext*,
+ ASTContext&);
+
+/// Filters out lookup results that don't fall within the given scope
+/// as determined by isDeclInScope.
+static void FilterLookupForScope(Sema &SemaRef, LookupResult &R,
+ DeclContext *Ctx, Scope *S,
+ bool ConsiderLinkage) {
+ LookupResult::Filter F = R.makeFilter();
+ while (F.hasNext()) {
+ NamedDecl *D = F.next();
+
+ if (SemaRef.isDeclInScope(D, Ctx, S))
+ continue;
+
+ if (ConsiderLinkage &&
+ isOutOfScopePreviousDeclaration(D, Ctx, SemaRef.Context))
+ continue;
+
+ F.erase();
+ }
+
+ F.done();
+}
+
+static bool isUsingDecl(NamedDecl *D) {
+ return isa<UsingShadowDecl>(D) ||
+ isa<UnresolvedUsingTypenameDecl>(D) ||
+ isa<UnresolvedUsingValueDecl>(D);
+}
+
+/// Removes using shadow declarations from the lookup results.
+static void RemoveUsingDecls(LookupResult &R) {
+ LookupResult::Filter F = R.makeFilter();
+ while (F.hasNext())
+ if (isUsingDecl(F.next()))
+ F.erase();
+
+ F.done();
+}
+
static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) {
if (D->isUsed() || D->hasAttr<UnusedAttr>())
return false;
@@ -572,11 +616,10 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid,
/// how to resolve this situation, merging decls or emitting
/// diagnostics as appropriate. If there was an error, set New to be invalid.
///
-void Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) {
- // If either decl is known invalid already, set the new one to be invalid and
- // don't bother doing any merging checks.
- if (New->isInvalidDecl() || OldD->isInvalidDecl())
- return New->setInvalidDecl();
+void Sema::MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls) {
+ // If the new decl is known invalid already, don't bother doing any
+ // merging checks.
+ if (New->isInvalidDecl()) return;
// Allow multiple definitions for ObjC built-in typedefs.
// FIXME: Verify the underlying types are equivalent!
@@ -611,16 +654,25 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) {
}
// Fall through - the typedef name was not a builtin type.
}
+
// Verify the old decl was also a type.
- TypeDecl *Old = dyn_cast<TypeDecl>(OldD);
- if (!Old) {
+ TypeDecl *Old = 0;
+ if (!OldDecls.isSingleResult() ||
+ !(Old = dyn_cast<TypeDecl>(OldDecls.getFoundDecl()))) {
Diag(New->getLocation(), diag::err_redefinition_different_kind)
<< New->getDeclName();
+
+ NamedDecl *OldD = OldDecls.getRepresentativeDecl();
if (OldD->getLocation().isValid())
Diag(OldD->getLocation(), diag::note_previous_definition);
+
return New->setInvalidDecl();
}
+ // If the old declaration is invalid, just give up here.
+ if (Old->isInvalidDecl())
+ return New->setInvalidDecl();
+
// Determine the "old" type we'll use for checking and diagnostics.
QualType OldType;
if (TypedefDecl *OldTypedef = dyn_cast<TypedefDecl>(Old))
@@ -977,18 +1029,19 @@ bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) {
/// FinalizeDeclaratorGroup. Unfortunately, we can't analyze tentative
/// definitions here, since the initializer hasn't been attached.
///
-void Sema::MergeVarDecl(VarDecl *New, Decl *OldD) {
- // If either decl is invalid, make sure the new one is marked invalid and
- // don't do any other checking.
- if (New->isInvalidDecl() || OldD->isInvalidDecl())
- return New->setInvalidDecl();
+void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
+ // If the new decl is already invalid, don't do any other checking.
+ if (New->isInvalidDecl())
+ return;
// Verify the old decl was also a variable.
- VarDecl *Old = dyn_cast<VarDecl>(OldD);
- if (!Old) {
+ VarDecl *Old = 0;
+ if (!Previous.isSingleResult() ||
+ !(Old = dyn_cast<VarDecl>(Previous.getFoundDecl()))) {
Diag(New->getLocation(), diag::err_redefinition_different_kind)
<< New->getDeclName();
- Diag(OldD->getLocation(), diag::note_previous_definition);
+ Diag(Previous.getRepresentativeDecl()->getLocation(),
+ diag::note_previous_definition);
return New->setInvalidDecl();
}
@@ -1403,6 +1456,33 @@ Sema::DeclPtrTy Sema::ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) {
return DeclPtrTy::make(Tag);
}
+/// We are trying to introduce the given name into the given context;
+/// check if there's an existing declaration that can't be overloaded.
+///
+/// \return true if this is a forbidden redeclaration
+bool Sema::CheckRedeclaration(DeclContext *DC,
+ DeclarationName Name,
+ SourceLocation NameLoc,
+ unsigned diagnostic) {
+ LookupResult R(*this, Name, NameLoc, LookupOrdinaryName,
+ ForRedeclaration);
+ LookupQualifiedName(R, DC);
+
+ if (R.empty()) return false;
+
+ if (R.getResultKind() == LookupResult::Found &&
+ isa<TagDecl>(R.getFoundDecl()))
+ return false;
+
+ // Pick a representative declaration.
+ NamedDecl *PrevDecl = (*R.begin())->getUnderlyingDecl();
+
+ Diag(NameLoc, diagnostic) << Name;
+ Diag(PrevDecl->getLocation(), diag::note_previous_declaration);
+
+ return true;
+}
+
/// InjectAnonymousStructOrUnionMembers - Inject the members of the
/// anonymous struct or union AnonRecord into the owning context Owner
/// and scope S. This routine will be invoked just after we realize
@@ -1421,26 +1501,21 @@ Sema::DeclPtrTy Sema::ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) {
/// structs/unions into the owning context and scope as well.
bool Sema::InjectAnonymousStructOrUnionMembers(Scope *S, DeclContext *Owner,
RecordDecl *AnonRecord) {
+ unsigned diagKind
+ = AnonRecord->isUnion() ? diag::err_anonymous_union_member_redecl
+ : diag::err_anonymous_struct_member_redecl;
+
bool Invalid = false;
for (RecordDecl::field_iterator F = AnonRecord->field_begin(),
FEnd = AnonRecord->field_end();
F != FEnd; ++F) {
if ((*F)->getDeclName()) {
- LookupResult R(*this, (*F)->getDeclName(), SourceLocation(),
- LookupOrdinaryName, ForRedeclaration);
- LookupQualifiedName(R, Owner);
- NamedDecl *PrevDecl = R.getAsSingleDecl(Context);
- if (PrevDecl && !isa<TagDecl>(PrevDecl)) {
+ if (CheckRedeclaration(Owner, (*F)->getDeclName(),
+ (*F)->getLocation(), diagKind)) {
// C++ [class.union]p2:
// The names of the members of an anonymous union shall be
// distinct from the names of any other entity in the
// scope in which the anonymous union is declared.
- unsigned diagKind
- = AnonRecord->isUnion()? diag::err_anonymous_union_member_redecl
- : diag::err_anonymous_struct_member_redecl;
- Diag((*F)->getLocation(), diagKind)
- << (*F)->getDeclName();
- Diag(PrevDecl->getLocation(), diag::note_previous_declaration);
Invalid = true;
} else {
// C++ [class.union]p2:
@@ -1765,19 +1840,20 @@ Sema::HandleDeclarator(Scope *S, Declarator &D,
}
DeclContext *DC;
- NamedDecl *PrevDecl;
NamedDecl *New;
DeclaratorInfo *DInfo = 0;
QualType R = GetTypeForDeclarator(D, S, &DInfo);
+ LookupResult Previous(*this, Name, D.getIdentifierLoc(), LookupOrdinaryName,
+ ForRedeclaration);
+
// See if this is a redefinition of a variable in the same scope.
if (D.getCXXScopeSpec().isInvalid()) {
DC = CurContext;
- PrevDecl = 0;
D.setInvalidType();
} else if (!D.getCXXScopeSpec().isSet()) {
- LookupNameKind NameKind = LookupOrdinaryName;
+ bool IsLinkageLookup = false;
// If the declaration we're planning to build will be a function
// or object with linkage, then look for another declaration with
@@ -1787,19 +1863,18 @@ Sema::HandleDeclarator(Scope *S, Declarator &D,
else if (R->isFunctionType()) {
if (CurContext->isFunctionOrMethod() ||
D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static)
- NameKind = LookupRedeclarationWithLinkage;
+ IsLinkageLookup = true;
} else if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_extern)
- NameKind = LookupRedeclarationWithLinkage;
+ IsLinkageLookup = true;
else if (CurContext->getLookupContext()->isTranslationUnit() &&
D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static)
- NameKind = LookupRedeclarationWithLinkage;
+ IsLinkageLookup = true;
- DC = CurContext;
- LookupResult R(*this, Name, D.getIdentifierLoc(), NameKind,
- ForRedeclaration);
+ if (IsLinkageLookup)
+ Previous.clear(LookupRedeclarationWithLinkage);
- LookupName(R, S, NameKind == LookupRedeclarationWithLinkage);
- PrevDecl = R.getAsSingleDecl(Context);
+ DC = CurContext;
+ LookupName(Previous, S, /* CreateBuiltins = */ IsLinkageLookup);
} else { // Something like "int foo::x;"
DC = computeDeclContext(D.getCXXScopeSpec(), true);
@@ -1819,10 +1894,11 @@ Sema::HandleDeclarator(Scope *S, Declarator &D,
RequireCompleteDeclContext(D.getCXXScopeSpec()))
return DeclPtrTy();
- LookupResult Res(*this, Name, D.getIdentifierLoc(), LookupOrdinaryName,
- ForRedeclaration);
- LookupQualifiedName(Res, DC);
- PrevDecl = Res.getAsSingleDecl(Context);
+ LookupQualifiedName(Previous, DC);
+
+ // Don't consider using declarations as previous declarations for
+ // out-of-line members.
+ RemoveUsingDecls(Previous);
// C++ 7.3.1.2p2:
// Members (including explicit specializations of templates) of a named
@@ -1870,23 +1946,25 @@ Sema::HandleDeclarator(Scope *S, Declarator &D,
}
}
- if (PrevDecl && PrevDecl->isTemplateParameter()) {
+ if (Previous.isSingleResult() &&
+ Previous.getFoundDecl()->isTemplateParameter()) {
// Maybe we will complain about the shadowed template parameter.
if (!D.isInvalidType())
- if (DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl))
+ if (DiagnoseTemplateParameterShadow(D.getIdentifierLoc(),
+ Previous.getFoundDecl()))
D.setInvalidType();
// Just pretend that we didn't see the previous declaration.
- PrevDecl = 0;
+ Previous.clear();
}
// In C++, the previous declaration we find might be a tag type
// (class or enum). In this case, the new declaration will hide the
// tag type. Note that this does does not apply if we're declaring a
// typedef (C++ [dcl.typedef]p4).
- if (PrevDecl && PrevDecl->getIdentifierNamespace() == Decl::IDNS_Tag &&
+ if (Previous.isSingleTagDecl() &&
D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef)
- PrevDecl = 0;
+ Previous.clear();
bool Redeclaration = false;
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) {
@@ -1895,13 +1973,13 @@ Sema::HandleDeclarator(Scope *S, Declarator &D,
return DeclPtrTy();
}
- New = ActOnTypedefDeclarator(S, D, DC, R, DInfo, PrevDecl, Redeclaration);
+ New = ActOnTypedefDeclarator(S, D, DC, R, DInfo, Previous, Redeclaration);
} else if (R->isFunctionType()) {
- New = ActOnFunctionDeclarator(S, D, DC, R, DInfo, PrevDecl,
+ New = ActOnFunctionDeclarator(S, D, DC, R, DInfo, Previous,
move(TemplateParamLists),
IsFunctionDefinition, Redeclaration);
} else {
- New = ActOnVariableDeclarator(S, D, DC, R, DInfo, PrevDecl,
+ New = ActOnVariableDeclarator(S, D, DC, R, DInfo, Previous,
move(TemplateParamLists),
Redeclaration);
}
@@ -1970,16 +2048,19 @@ static QualType TryToFixInvalidVariablyModifiedType(QualType T,
/// \brief Register the given locally-scoped external C declaration so
/// that it can be found later for redeclarations
void
-Sema::RegisterLocallyScopedExternCDecl(NamedDecl *ND, NamedDecl *PrevDecl,
+Sema::RegisterLocallyScopedExternCDecl(NamedDecl *ND,
+ const LookupResult &Previous,
Scope *S) {
assert(ND->getLexicalDeclContext()->isFunctionOrMethod() &&
"Decl is not a locally-scoped decl!");
// Note that we have a locally-scoped external with this name.
LocallyScopedExternalDecls[ND->getDeclName()] = ND;
- if (!PrevDecl)
+ if (!Previous.isSingleResult())
return;
+ NamedDecl *PrevDecl = Previous.getFoundDecl();
+
// If there was a previous declaration of this variable, it may be
// in our identifier chain. Update the identifier chain with the new
// declaration.
@@ -2015,7 +2096,7 @@ void Sema::DiagnoseFunctionSpecifiers(Declarator& D) {
NamedDecl*
Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
QualType R, DeclaratorInfo *DInfo,
- NamedDecl* PrevDecl, bool &Redeclaration) {
+ LookupResult &Previous, bool &Redeclaration) {
// Typedef declarators cannot be qualified (C++ [dcl.meaning]p1).
if (D.getCXXScopeSpec().isSet()) {
Diag(D.getIdentifierLoc(), diag::err_qualified_typedef_declarator)
@@ -2040,11 +2121,13 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// Handle attributes prior to checking for duplicates in MergeVarDecl
ProcessDeclAttributes(S, NewTD, D);
+
// Merge the decl with the existing one if appropriate. If the decl is
// in an outer scope, it isn't the same thing.
- if (PrevDecl && isDeclInScope(PrevDecl, DC, S)) {
+ FilterLookupForScope(*this, Previous, DC, S, /*ConsiderLinkage*/ false);
+ if (!Previous.empty()) {
Redeclaration = true;
- MergeTypeDefDecl(NewTD, PrevDecl);
+ MergeTypeDefDecl(NewTD, Previous);
}
// C99 6.7.7p2: If a typedef name specifies a variably modified type
@@ -2155,7 +2238,7 @@ isOutOfScopePreviousDeclaration(NamedDecl *PrevDecl, DeclContext *DC,
NamedDecl*
Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
QualType R, DeclaratorInfo *DInfo,
- NamedDecl* PrevDecl,
+ LookupResult &Previous,
MultiTemplateParamsArg TemplateParamLists,
bool &Redeclaration) {
DeclarationName Name = GetNameForDeclarator(D);
@@ -2285,22 +2368,21 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
SE->getByteLength())));
}
- // If name lookup finds a previous declaration that is not in the
- // same scope as the new declaration, this may still be an
- // acceptable redeclaration.
- if (PrevDecl && !isDeclInScope(PrevDecl, DC, S) &&
- !(NewVD->hasLinkage() &&
- isOutOfScopePreviousDeclaration(PrevDecl, DC, Context)))
- PrevDecl = 0;
+ // Don't consider existing declarations that are in a different
+ // scope and are out-of-semantic-context declarations (if the new
+ // declaration has linkage).
+ FilterLookupForScope(*this, Previous, DC, S, NewVD->hasLinkage());
// Merge the decl with the existing one if appropriate.
- if (PrevDecl) {
- if (isa<FieldDecl>(PrevDecl) && D.getCXXScopeSpec().isSet()) {
+ if (!Previous.empty()) {
+ if (Previous.isSingleResult() &&
+ isa<FieldDecl>(Previous.getFoundDecl()) &&
+ D.getCXXScopeSpec().isSet()) {
// The user tried to define a non-static data member
// out-of-line (C++ [dcl.meaning]p1).
Diag(NewVD->getLocation(), diag::err_nonstatic_member_out_of_line)
<< D.getCXXScopeSpec().getRange();
- PrevDecl = 0;
+ Previous.clear();
NewVD->setInvalidDecl();
}
} else if (D.getCXXScopeSpec().isSet()) {
@@ -2311,17 +2393,18 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
NewVD->setInvalidDecl();
}
- CheckVariableDeclaration(NewVD, PrevDecl, Redeclaration);
+ CheckVariableDeclaration(NewVD, Previous, Redeclaration);
// This is an explicit specialization of a static data member. Check it.
if (isExplicitSpecialization && !NewVD->isInvalidDecl() &&
- CheckMemberSpecialization(NewVD, PrevDecl))
+ CheckMemberSpecialization(NewVD, Previous))
NewVD->setInvalidDecl();
-
+
// attributes declared post-definition are currently ignored
- if (PrevDecl) {
- const VarDecl *Def = 0, *PrevVD = dyn_cast<VarDecl>(PrevDecl);
- if (PrevVD->getDefinition(Def) && D.hasAttributes()) {
+ if (Previous.isSingleResult()) {
+ const VarDecl *Def = 0;
+ VarDecl *PrevDecl = dyn_cast<VarDecl>(Previous.getFoundDecl());
+ if (PrevDecl && PrevDecl->getDefinition(Def) && D.hasAttributes()) {
Diag(NewVD->getLocation(), diag::warn_attribute_precede_definition);
Diag(Def->getLocation(), diag::note_previous_definition);
}
@@ -2331,7 +2414,7 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// such variables.
if (CurContext->isFunctionOrMethod() && NewVD->isExternC() &&
!NewVD->isInvalidDecl())
- RegisterLocallyScopedExternCDecl(NewVD, PrevDecl, S);
+ RegisterLocallyScopedExternCDecl(NewVD, Previous, S);
return NewVD;
}
@@ -2346,7 +2429,8 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
/// that have been instantiated from a template.
///
/// Sets NewVD->isInvalidDecl() if an error was encountered.
-void Sema::CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl,
+void Sema::CheckVariableDeclaration(VarDecl *NewVD,
+ LookupResult &Previous,
bool &Redeclaration) {
// If the decl is already known invalid, don't check it.
if (NewVD->isInvalidDecl())
@@ -2419,14 +2503,14 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl,
NewVD->setType(FixedTy);
}
- if (!PrevDecl && NewVD->isExternC()) {
+ if (Previous.empty() && NewVD->isExternC()) {
// Since we did not find anything by this name and we're declaring
// an extern "C" variable, look for a non-visible extern "C"
// declaration with the same name.
llvm::DenseMap<DeclarationName, NamedDecl *>::iterator Pos
= LocallyScopedExternalDecls.find(NewVD->getDeclName());
if (Pos != LocallyScopedExternalDecls.end())
- PrevDecl = Pos->second;
+ Previous.addDecl(Pos->second);
}
if (T->isVoidType() && !NewVD->hasExternalStorage()) {
@@ -2445,18 +2529,12 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl,
return NewVD->setInvalidDecl();
}
- if (PrevDecl) {
+ if (!Previous.empty()) {
Redeclaration = true;
- MergeVarDecl(NewVD, PrevDecl);
+ MergeVarDecl(NewVD, Previous);
}
}
-static bool isUsingDecl(Decl *D) {
- return isa<UsingDecl>(D) ||
- isa<UnresolvedUsingTypenameDecl>(D) ||
- isa<UnresolvedUsingValueDecl>(D);
-}
-
/// \brief Data used with FindOverriddenMethod
struct FindOverriddenMethodData {
Sema *S;
@@ -2477,8 +2555,7 @@ static bool FindOverriddenMethod(const CXXBaseSpecifier *Specifier,
Path.Decls.first != Path.Decls.second;
++Path.Decls.first) {
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(*Path.Decls.first)) {
- OverloadedFunctionDecl::function_iterator MatchedDecl;
- if (MD->isVirtual() && !Data->S->IsOverload(Data->Method, MD, MatchedDecl))
+ if (MD->isVirtual() && !Data->S->IsOverload(Data->Method, MD))
return true;
}
}
@@ -2486,10 +2563,30 @@ static bool FindOverriddenMethod(const CXXBaseSpecifier *Specifier,
return false;
}
+/// AddOverriddenMethods - See if a method overrides any in the base classes,
+/// and if so, check that it's a valid override and remember it.
+void Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) {
+ // Look for virtual methods in base classes that this method might override.
+ CXXBasePaths Paths;
+ FindOverriddenMethodData Data;
+ Data.Method = MD;
+ Data.S = this;
+ if (DC->lookupInBases(&FindOverriddenMethod, &Data, Paths)) {
+ for (CXXBasePaths::decl_iterator I = Paths.found_decls_begin(),
+ E = Paths.found_decls_end(); I != E; ++I) {
+ if (CXXMethodDecl *OldMD = dyn_cast<CXXMethodDecl>(*I)) {
+ if (!CheckOverridingFunctionReturnType(MD, OldMD) &&
+ !CheckOverridingFunctionExceptionSpec(MD, OldMD))
+ MD->addOverriddenMethod(OldMD);
+ }
+ }
+ }
+}
+
NamedDecl*
Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
QualType R, DeclaratorInfo *DInfo,
- NamedDecl* PrevDecl,
+ LookupResult &Previous,
MultiTemplateParamsArg TemplateParamLists,
bool IsFunctionDefinition, bool &Redeclaration) {
assert(R.getTypePtr()->isFunctionType());
@@ -2554,10 +2651,6 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
FunctionDecl *NewFD;
if (isFriend) {
- // DC is the namespace in which the function is being declared.
- assert((DC->isFileContext() || PrevDecl) && "previously-undeclared "
- "friend function being created in a non-namespace context");
-
// C++ [class.friend]p5
// A function can be defined in a friend declaration of a
// class . . . . Such a function is implicitly inline.
@@ -2733,37 +2826,29 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
}
}
+ // Filter out previous declarations that don't match the scope.
+ FilterLookupForScope(*this, Previous, DC, S, NewFD->hasLinkage());
+
if (isFriend) {
+ // DC is the namespace in which the function is being declared.
+ assert((DC->isFileContext() || !Previous.empty()) &&
+ "previously-undeclared friend function being created "
+ "in a non-namespace context");
+
if (FunctionTemplate) {
FunctionTemplate->setObjectOfFriendDecl(
- /* PreviouslyDeclared= */ PrevDecl != NULL);
+ /* PreviouslyDeclared= */ !Previous.empty());
FunctionTemplate->setAccess(AS_public);
}
else
- NewFD->setObjectOfFriendDecl(/* PreviouslyDeclared= */ PrevDecl != NULL);
+ NewFD->setObjectOfFriendDecl(/* PreviouslyDeclared= */ !Previous.empty());
NewFD->setAccess(AS_public);
}
- if (CXXMethodDecl *NewMD = dyn_cast<CXXMethodDecl>(NewFD)) {
- // Look for virtual methods in base classes that this method might override.
- CXXBasePaths Paths;
- FindOverriddenMethodData Data;
- Data.Method = NewMD;
- Data.S = this;
- if (cast<CXXRecordDecl>(DC)->lookupInBases(&FindOverriddenMethod, &Data,
- Paths)) {
- for (CXXBasePaths::decl_iterator I = Paths.found_decls_begin(),
- E = Paths.found_decls_end(); I != E; ++I) {
- if (CXXMethodDecl *OldMD = dyn_cast<CXXMethodDecl>(*I)) {
- if (!CheckOverridingFunctionReturnType(NewMD, OldMD) &&
- !CheckOverridingFunctionExceptionSpec(NewMD, OldMD))
- NewMD->addOverriddenMethod(OldMD);
- }
- }
- }
- }
+ if (CXXMethodDecl *NewMD = dyn_cast<CXXMethodDecl>(NewFD))
+ AddOverriddenMethods(cast<CXXRecordDecl>(DC), NewMD);
if (SC == FunctionDecl::Static && isa<CXXMethodDecl>(NewFD) &&
!CurContext->isRecord()) {
@@ -2847,14 +2932,6 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// Finally, we know we have the right number of parameters, install them.
NewFD->setParams(Context, Params.data(), Params.size());
- // If name lookup finds a previous declaration that is not in the
- // same scope as the new declaration, this may still be an
- // acceptable redeclaration.
- if (PrevDecl && !isDeclInScope(PrevDecl, DC, S) &&
- !(NewFD->hasLinkage() &&
- isOutOfScopePreviousDeclaration(PrevDecl, DC, Context)))
- PrevDecl = 0;
-
// If the declarator is a template-id, translate the parser's template
// argument list into our AST format.
bool HasExplicitTemplateArgs = false;
@@ -2891,22 +2968,26 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
isFunctionTemplateSpecialization = true;
}
}
-
+
if (isFunctionTemplateSpecialization) {
if (CheckFunctionTemplateSpecialization(NewFD, HasExplicitTemplateArgs,
LAngleLoc, TemplateArgs.data(),
TemplateArgs.size(), RAngleLoc,
- PrevDecl))
+ Previous))
NewFD->setInvalidDecl();
} else if (isExplicitSpecialization && isa<CXXMethodDecl>(NewFD) &&
- CheckMemberSpecialization(NewFD, PrevDecl))
+ CheckMemberSpecialization(NewFD, Previous))
NewFD->setInvalidDecl();
// Perform semantic checking on the function declaration.
bool OverloadableAttrRequired = false; // FIXME: HACK!
- CheckFunctionDeclaration(NewFD, PrevDecl, isExplicitSpecialization,
+ CheckFunctionDeclaration(NewFD, Previous, isExplicitSpecialization,
Redeclaration, /*FIXME:*/OverloadableAttrRequired);
+ assert((NewFD->isInvalidDecl() || !Redeclaration ||
+ Previous.getResultKind() != LookupResult::FoundOverloaded) &&
+ "previous declaration set still overloaded");
+
if (D.getCXXScopeSpec().isSet() && !NewFD->isInvalidDecl()) {
// An out-of-line member function declaration must also be a
// definition (C++ [dcl.meaning]p1).
@@ -2918,7 +2999,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
Diag(NewFD->getLocation(), diag::err_out_of_line_declaration)
<< D.getCXXScopeSpec().getRange();
NewFD->setInvalidDecl();
- } else if (!Redeclaration && (!PrevDecl || !isUsingDecl(PrevDecl))) {
+ } else if (!Redeclaration) {
// The user tried to provide an out-of-line definition for a
// function that is a member of a class or namespace, but there
// was no such member function declared (C++ [class.mfct]p2,
@@ -2948,8 +3029,6 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
isNearlyMatchingFunction(Context, cast<FunctionDecl>(*Func), NewFD))
Diag((*Func)->getLocation(), diag::note_member_def_close_match);
}
-
- PrevDecl = 0;
}
}
@@ -2960,8 +3039,9 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
ProcessDeclAttributes(S, NewFD, D);
// attributes declared post-definition are currently ignored
- if (Redeclaration && PrevDecl) {
- const FunctionDecl *Def, *PrevFD = dyn_cast<FunctionDecl>(PrevDecl);
+ if (Redeclaration && Previous.isSingleResult()) {
+ const FunctionDecl *Def;
+ FunctionDecl *PrevFD = dyn_cast<FunctionDecl>(Previous.getFoundDecl());
if (PrevFD && PrevFD->getBody(Def) && D.hasAttributes()) {
Diag(NewFD->getLocation(), diag::warn_attribute_precede_definition);
Diag(Def->getLocation(), diag::note_previous_definition);
@@ -2975,8 +3055,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// with that name must be marked "overloadable".
Diag(NewFD->getLocation(), diag::err_attribute_overloadable_missing)
<< Redeclaration << NewFD;
- if (PrevDecl)
- Diag(PrevDecl->getLocation(),
+ if (!Previous.empty())
+ Diag(Previous.getRepresentativeDecl()->getLocation(),
diag::note_attribute_overloadable_prev_overload);
NewFD->addAttr(::new (Context) OverloadableAttr());
}
@@ -2985,7 +3065,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// map of such names.
if (CurContext->isFunctionOrMethod() && NewFD->isExternC()
&& !NewFD->isInvalidDecl())
- RegisterLocallyScopedExternCDecl(NewFD, PrevDecl, S);
+ RegisterLocallyScopedExternCDecl(NewFD, Previous, S);
// Set this FunctionDecl's range up to the right paren.
NewFD->setLocEnd(D.getSourceRange().getEnd());
@@ -3013,7 +3093,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
/// an explicit specialization of the previous declaration.
///
/// This sets NewFD->isInvalidDecl() to true if there was an error.
-void Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl,
+void Sema::CheckFunctionDeclaration(FunctionDecl *NewFD,
+ LookupResult &Previous,
bool IsExplicitSpecialization,
bool &Redeclaration,
bool &OverloadableAttrRequired) {
@@ -3032,27 +3113,26 @@ void Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl,
CheckMain(NewFD);
// Check for a previous declaration of this name.
- if (!PrevDecl && NewFD->isExternC()) {
+ if (Previous.empty() && NewFD->isExternC()) {
// Since we did not find anything by this name and we're declaring
// an extern "C" function, look for a non-visible extern "C"
// declaration with the same name.
llvm::DenseMap<DeclarationName, NamedDecl *>::iterator Pos
= LocallyScopedExternalDecls.find(NewFD->getDeclName());
if (Pos != LocallyScopedExternalDecls.end())
- PrevDecl = Pos->second;
+ Previous.addDecl(Pos->second);
}
// Merge or overload the declaration with an existing declaration of
// the same name, if appropriate.
- if (PrevDecl) {
+ if (!Previous.empty()) {
// Determine whether NewFD is an overload of PrevDecl or
// a declaration that requires merging. If it's an overload,
// there's no more work to do here; we'll just add the new
// function to the scope.
- OverloadedFunctionDecl::function_iterator MatchedDecl;
if (!getLangOptions().CPlusPlus &&
- AllowOverloadingOfFunction(PrevDecl, Context)) {
+ AllowOverloadingOfFunction(Previous, Context)) {
OverloadableAttrRequired = true;
// Functions marked "overloadable" must have a prototype (that
@@ -3071,22 +3151,26 @@ void Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl,
}
}
- if (PrevDecl &&
- (!AllowOverloadingOfFunction(PrevDecl, Context) ||
- !IsOverload(NewFD, PrevDecl, MatchedDecl)) && !isUsingDecl(PrevDecl)) {
- Redeclaration = true;
- Decl *OldDecl = PrevDecl;
-
- // If PrevDecl was an overloaded function, extract the
- // FunctionDecl that matched.
- if (isa<OverloadedFunctionDecl>(PrevDecl))
- OldDecl = *MatchedDecl;
+ NamedDecl *OldDecl = 0;
+ if (!Previous.empty()) {
+ if (!AllowOverloadingOfFunction(Previous, Context)) {
+ Redeclaration = true;
+ OldDecl = Previous.getFoundDecl();
+ } else if (!IsOverload(NewFD, Previous, OldDecl)) {
+ if (!isUsingDecl(OldDecl))
+ Redeclaration = true;
+ }
+ }
+ if (Redeclaration) {
// NewFD and OldDecl represent declarations that need to be
// merged.
if (MergeFunctionDecl(NewFD, OldDecl))
return NewFD->setInvalidDecl();
+ Previous.clear();
+ Previous.addDecl(OldDecl);
+
if (FunctionTemplateDecl *OldTemplateDecl
= dyn_cast<FunctionTemplateDecl>(OldDecl)) {
NewFD->setPreviousDeclaration(OldTemplateDecl->getTemplatedDecl());
@@ -4313,11 +4397,13 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
DeclContext *SearchDC = CurContext;
DeclContext *DC = CurContext;
- NamedDecl *PrevDecl = 0;
bool isStdBadAlloc = false;
bool Invalid = false;
- RedeclarationKind Redecl = (RedeclarationKind) (TUK != TUK_Reference);
+ RedeclarationKind Redecl = (TUK != TUK_Reference ? ForRedeclaration
+ : NotForRedeclaration);
+
+ LookupResult Previous(*this, Name, NameLoc, LookupTagName, Redecl);
if (Name && SS.isNotEmpty()) {
// We have a nested-name tag ('struct foo::bar').
@@ -4344,17 +4430,13 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
DC = computeDeclContext(SS, true);
SearchDC = DC;
// Look-up name inside 'foo::'.
- LookupResult R(*this, Name, NameLoc, LookupTagName, Redecl);
- LookupQualifiedName(R, DC);
+ LookupQualifiedName(Previous, DC);
- if (R.isAmbiguous())
+ if (Previous.isAmbiguous())
return DeclPtrTy();
- if (R.getResultKind() == LookupResult::Found)
- PrevDecl = dyn_cast<TagDecl>(R.getFoundDecl());
-
// A tag 'foo::bar' must already exist.
- if (!PrevDecl) {
+ if (Previous.empty()) {
Diag(NameLoc, diag::err_not_tag_in_scope) << Name << SS.getRange();
Name = 0;
Invalid = true;
@@ -4366,19 +4448,11 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// FIXME: We're looking into outer scopes here, even when we
// shouldn't be. Doing so can result in ambiguities that we
// shouldn't be diagnosing.
- LookupResult R(*this, Name, NameLoc, LookupTagName, Redecl);
- LookupName(R, S);
- if (R.isAmbiguous()) {
- // FIXME: This is not best way to recover from case like:
- //
- // struct S s;
- //
- // causes needless "incomplete type" error later.
- Name = 0;
- PrevDecl = 0;
- Invalid = true;
- } else
- PrevDecl = R.getAsSingleDecl(Context);
+ LookupName(Previous, S);
+
+ // Note: there used to be some attempt at recovery here.
+ if (Previous.isAmbiguous())
+ return DeclPtrTy();
if (!getLangOptions().CPlusPlus && TUK != TUK_Reference) {
// FIXME: This makes sure that we ignore the contexts associated
@@ -4390,11 +4464,12 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
}
}
- if (PrevDecl && PrevDecl->isTemplateParameter()) {
+ if (Previous.isSingleResult() &&
+ Previous.getFoundDecl()->isTemplateParameter()) {
// Maybe we will complain about the shadowed template parameter.
- DiagnoseTemplateParameterShadow(NameLoc, PrevDecl);
+ DiagnoseTemplateParameterShadow(NameLoc, Previous.getFoundDecl());
// Just pretend that we didn't see the previous declaration.
- PrevDecl = 0;
+ Previous.clear();
}
if (getLangOptions().CPlusPlus && Name && DC && StdNamespace &&
@@ -4402,15 +4477,17 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// This is a declaration of or a reference to "std::bad_alloc".
isStdBadAlloc = true;
- if (!PrevDecl && StdBadAlloc) {
+ if (Previous.empty() && StdBadAlloc) {
// std::bad_alloc has been implicitly declared (but made invisible to
// name lookup). Fill in this implicit declaration as the previous
// declaration, so that the declarations get chained appropriately.
- PrevDecl = StdBadAlloc;
+ Previous.addDecl(StdBadAlloc);
}
}
-
- if (PrevDecl) {
+
+ if (!Previous.empty()) {
+ assert(Previous.isSingleResult());
+ NamedDecl *PrevDecl = Previous.getFoundDecl();
if (TagDecl *PrevTagDecl = dyn_cast<TagDecl>(PrevDecl)) {
// If this is a use of a previous tag, or if the tag is already declared
// in the same scope (so that the definition/declaration completes or
@@ -4430,14 +4507,14 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
PrevTagDecl->getKindName());
else
Diag(KWLoc, diag::err_use_with_wrong_tag) << Name;
- Diag(PrevDecl->getLocation(), diag::note_previous_use);
+ Diag(PrevTagDecl->getLocation(), diag::note_previous_use);
if (SafeToContinue)
Kind = PrevTagDecl->getTagKind();
else {
// Recover by making this an anonymous redefinition.
Name = 0;
- PrevDecl = 0;
+ Previous.clear();
Invalid = true;
}
}
@@ -4450,7 +4527,7 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// For our current ASTs this shouldn't be a problem, but will
// need to be changed with DeclGroups.
if (TUK == TUK_Reference || TUK == TUK_Friend)
- return DeclPtrTy::make(PrevDecl);
+ return DeclPtrTy::make(PrevTagDecl);
// Diagnose attempts to redefine a tag.
if (TUK == TUK_Definition) {
@@ -4468,7 +4545,7 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// struct be anonymous, which will make any later
// references get the previous definition.
Name = 0;
- PrevDecl = 0;
+ Previous.clear();
Invalid = true;
}
} else {
@@ -4480,7 +4557,7 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
Diag(PrevTagDecl->getLocation(),
diag::note_previous_definition);
Name = 0;
- PrevDecl = 0;
+ Previous.clear();
Invalid = true;
}
}
@@ -4497,7 +4574,7 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// scope, e.g. "struct foo; void bar() { struct foo; }", just create a
// new decl/type. We set PrevDecl to NULL so that the entities
// have distinct types.
- PrevDecl = 0;
+ Previous.clear();
}
// If we get here, we're going to create a new Decl. If PrevDecl
// is non-NULL, it's a definition of the tag declared by
@@ -4511,12 +4588,12 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
Diag(NameLoc, diag::err_redefinition_different_kind) << Name;
Diag(PrevDecl->getLocation(), diag::note_previous_definition);
Name = 0;
- PrevDecl = 0;
+ Previous.clear();
Invalid = true;
} else {
// The existing declaration isn't relevant to us; we're in a
// new scope, so clear out the previous declaration.
- PrevDecl = 0;
+ Previous.clear();
}
}
} else if (TUK == TUK_Reference && SS.isEmpty() && Name &&
@@ -4570,6 +4647,10 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
CreateNewDecl:
+ TagDecl *PrevDecl = 0;
+ if (Previous.isSingleResult())
+ PrevDecl = cast<TagDecl>(Previous.getFoundDecl());
+
// If there is an identifier, use the location of the identifier as the
// location of the decl, otherwise use the location of the struct/union
// keyword.
@@ -4651,7 +4732,7 @@ CreateNewDecl:
// If this is a specialization of a member class (of a class template),
// check the specialization.
- if (isExplicitSpecialization && CheckMemberSpecialization(New, PrevDecl))
+ if (isExplicitSpecialization && CheckMemberSpecialization(New, Previous))
Invalid = true;
if (Invalid)
@@ -4671,7 +4752,7 @@ CreateNewDecl:
// Mark this as a friend decl if applicable.
if (TUK == TUK_Friend)
- New->setObjectOfFriendDecl(/* PreviouslyDeclared = */ PrevDecl != NULL);
+ New->setObjectOfFriendDecl(/* PreviouslyDeclared = */ !Previous.empty());
// Set the access specifier.
if (!Invalid && TUK != TUK_Friend)
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 237a869f9084..bda1a6993934 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -4668,7 +4668,8 @@ Sema::ActOnFriendFunctionDecl(Scope *S,
// FIXME: handle local classes
// Recover from invalid scope qualifiers as if they just weren't there.
- NamedDecl *PrevDecl = 0;
+ LookupResult Previous(*this, Name, D.getIdentifierLoc(), LookupOrdinaryName,
+ ForRedeclaration);
if (!ScopeQual.isInvalid() && ScopeQual.isSet()) {
// FIXME: RequireCompleteDeclContext
DC = computeDeclContext(ScopeQual);
@@ -4676,15 +4677,15 @@ Sema::ActOnFriendFunctionDecl(Scope *S,
// FIXME: handle dependent contexts
if (!DC) return DeclPtrTy();
- LookupResult R(*this, Name, Loc, LookupOrdinaryName, ForRedeclaration);
- LookupQualifiedName(R, DC);
- PrevDecl = R.getAsSingleDecl(Context);
+ LookupQualifiedName(Previous, DC);
// If searching in that context implicitly found a declaration in
// a different context, treat it like it wasn't found at all.
// TODO: better diagnostics for this case. Suggesting the right
// qualified scope would be nice...
- if (!PrevDecl || !PrevDecl->getDeclContext()->Equals(DC)) {
+ // FIXME: getRepresentativeDecl() is not right here at all
+ if (Previous.empty() ||
+ !Previous.getRepresentativeDecl()->getDeclContext()->Equals(DC)) {
D.setInvalidType();
Diag(Loc, diag::err_qualified_friend_not_found) << Name << T;
return DeclPtrTy();
@@ -4711,12 +4712,10 @@ Sema::ActOnFriendFunctionDecl(Scope *S,
while (DC->isRecord())
DC = DC->getParent();
- LookupResult R(*this, Name, Loc, LookupOrdinaryName, ForRedeclaration);
- LookupQualifiedName(R, DC);
- PrevDecl = R.getAsSingleDecl(Context);
+ LookupQualifiedName(Previous, DC);
// TODO: decide what we think about using declarations.
- if (PrevDecl)
+ if (!Previous.empty())
break;
if (DC->isFileContext()) break;
@@ -4728,7 +4727,8 @@ Sema::ActOnFriendFunctionDecl(Scope *S,
// C++0x changes this for both friend types and functions.
// Most C++ 98 compilers do seem to give an error here, so
// we do, too.
- if (PrevDecl && DC->Equals(CurContext) && !getLangOptions().CPlusPlus0x)
+ if (!Previous.empty() && DC->Equals(CurContext)
+ && !getLangOptions().CPlusPlus0x)
Diag(DS.getFriendSpecLoc(), diag::err_friend_is_member);
}
@@ -4745,7 +4745,7 @@ Sema::ActOnFriendFunctionDecl(Scope *S,
}
bool Redeclaration = false;
- NamedDecl *ND = ActOnFunctionDeclarator(S, D, DC, T, DInfo, PrevDecl,
+ NamedDecl *ND = ActOnFunctionDeclarator(S, D, DC, T, DInfo, Previous,
move(TemplateParams),
IsDefinition,
Redeclaration);
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index 0c5569caff00..7da37affdc1e 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -828,9 +828,10 @@ void Sema::WarnConflictingTypedMethods(ObjCMethodDecl *ImpMethodDecl,
for (ObjCMethodDecl::param_iterator IM = ImpMethodDecl->param_begin(),
IF = IntfMethodDecl->param_begin(), EM = ImpMethodDecl->param_end();
IM != EM; ++IM, ++IF) {
- if (Context.typesAreCompatible((*IF)->getType(), (*IM)->getType()) ||
- Context.QualifiedIdConformsQualifiedId((*IF)->getType(),
- (*IM)->getType()))
+ QualType ParmDeclTy = (*IF)->getType().getUnqualifiedType();
+ QualType ParmImpTy = (*IM)->getType().getUnqualifiedType();
+ if (Context.typesAreCompatible(ParmDeclTy, ParmImpTy) ||
+ Context.QualifiedIdConformsQualifiedId(ParmDeclTy, ParmImpTy))
continue;
Diag((*IM)->getLocation(), diag::warn_conflicting_param_types)
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 0eea169b0727..462bf13540eb 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -1445,6 +1445,12 @@ QualType Sema::CheckPointerToMemberOperands(
}
}
+ if (isa<CXXZeroInitValueExpr>(rex->IgnoreParens())) {
+ // Diagnose use of pointer-to-member type which when used as
+ // the functional cast in a pointer-to-member expression.
+ Diag(Loc, diag::err_pointer_to_member_type) << isIndirect;
+ return QualType();
+ }
// C++ 5.5p2
// The result is an object or a function of the type specified by the
// second operand.
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index 1f49b789d3f0..1957d7ff11b7 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -246,7 +246,11 @@ void LookupResult::resolveKind() {
unsigned N = Decls.size();
// Fast case: no possible ambiguity.
- if (N == 0) return;
+ if (N == 0) {
+ assert(ResultKind == NotFound);
+ return;
+ }
+
if (N == 1) {
if (isa<UnresolvedUsingValueDecl>(Decls[0]))
ResultKind = FoundUnresolvedValue;
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index adcd977e626d..daf5b7f36008 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -284,100 +284,102 @@ void ImplicitConversionSequence::DebugPrint() const {
// signature), IsOverload returns false and MatchedDecl will be set to
// point to the FunctionDecl for #2.
bool
-Sema::IsOverload(FunctionDecl *New, Decl* OldD,
- OverloadedFunctionDecl::function_iterator& MatchedDecl) {
- if (OverloadedFunctionDecl* Ovl = dyn_cast<OverloadedFunctionDecl>(OldD)) {
- // Is this new function an overload of every function in the
- // overload set?
- OverloadedFunctionDecl::function_iterator Func = Ovl->function_begin(),
- FuncEnd = Ovl->function_end();
- for (; Func != FuncEnd; ++Func) {
- if (!IsOverload(New, *Func, MatchedDecl)) {
- MatchedDecl = Func;
+Sema::IsOverload(FunctionDecl *New, LookupResult &Previous, NamedDecl *&Match) {
+ for (LookupResult::iterator I = Previous.begin(), E = Previous.end();
+ I != E; ++I) {
+ NamedDecl *Old = (*I)->getUnderlyingDecl();
+ if (FunctionTemplateDecl *OldT = dyn_cast<FunctionTemplateDecl>(Old)) {
+ if (!IsOverload(New, OldT->getTemplatedDecl())) {
+ Match = Old;
return false;
}
+ } else if (FunctionDecl *OldF = dyn_cast<FunctionDecl>(Old)) {
+ if (!IsOverload(New, OldF)) {
+ Match = Old;
+ return false;
+ }
+ } else {
+ // (C++ 13p1):
+ // Only function declarations can be overloaded; object and type
+ // declarations cannot be overloaded.
+ Match = Old;
+ return false;
}
+ }
- // This function overloads every function in the overload set.
- return true;
- } else if (FunctionTemplateDecl *Old = dyn_cast<FunctionTemplateDecl>(OldD))
- return IsOverload(New, Old->getTemplatedDecl(), MatchedDecl);
- else if (FunctionDecl* Old = dyn_cast<FunctionDecl>(OldD)) {
- FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate();
- FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate();
-
- // C++ [temp.fct]p2:
- // A function template can be overloaded with other function templates
- // and with normal (non-template) functions.
- if ((OldTemplate == 0) != (NewTemplate == 0))
- return true;
+ return true;
+}
- // Is the function New an overload of the function Old?
- QualType OldQType = Context.getCanonicalType(Old->getType());
- QualType NewQType = Context.getCanonicalType(New->getType());
+bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old) {
+ FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate();
+ FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate();
- // Compare the signatures (C++ 1.3.10) of the two functions to
- // determine whether they are overloads. If we find any mismatch
- // in the signature, they are overloads.
+ // C++ [temp.fct]p2:
+ // A function template can be overloaded with other function templates
+ // and with normal (non-template) functions.
+ if ((OldTemplate == 0) != (NewTemplate == 0))
+ return true;
- // If either of these functions is a K&R-style function (no
- // prototype), then we consider them to have matching signatures.
- if (isa<FunctionNoProtoType>(OldQType.getTypePtr()) ||
- isa<FunctionNoProtoType>(NewQType.getTypePtr()))
- return false;
+ // Is the function New an overload of the function Old?
+ QualType OldQType = Context.getCanonicalType(Old->getType());
+ QualType NewQType = Context.getCanonicalType(New->getType());
- FunctionProtoType* OldType = cast<FunctionProtoType>(OldQType);
- FunctionProtoType* NewType = cast<FunctionProtoType>(NewQType);
-
- // The signature of a function includes the types of its
- // parameters (C++ 1.3.10), which includes the presence or absence
- // of the ellipsis; see C++ DR 357).
- if (OldQType != NewQType &&
- (OldType->getNumArgs() != NewType->getNumArgs() ||
- OldType->isVariadic() != NewType->isVariadic() ||
- !std::equal(OldType->arg_type_begin(), OldType->arg_type_end(),
- NewType->arg_type_begin())))
- return true;
+ // Compare the signatures (C++ 1.3.10) of the two functions to
+ // determine whether they are overloads. If we find any mismatch
+ // in the signature, they are overloads.
- // C++ [temp.over.link]p4:
- // The signature of a function template consists of its function
- // signature, its return type and its template parameter list. The names
- // of the template parameters are significant only for establishing the
- // relationship between the template parameters and the rest of the
- // signature.
- //
- // We check the return type and template parameter lists for function
- // templates first; the remaining checks follow.
- if (NewTemplate &&
- (!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),
- OldTemplate->getTemplateParameters(),
- false, TPL_TemplateMatch) ||
- OldType->getResultType() != NewType->getResultType()))
- return true;
+ // If either of these functions is a K&R-style function (no
+ // prototype), then we consider them to have matching signatures.
+ if (isa<FunctionNoProtoType>(OldQType.getTypePtr()) ||
+ isa<FunctionNoProtoType>(NewQType.getTypePtr()))
+ return false;
- // If the function is a class member, its signature includes the
- // cv-qualifiers (if any) on the function itself.
- //
- // As part of this, also check whether one of the member functions
- // is static, in which case they are not overloads (C++
- // 13.1p2). While not part of the definition of the signature,
- // this check is important to determine whether these functions
- // can be overloaded.
- CXXMethodDecl* OldMethod = dyn_cast<CXXMethodDecl>(Old);
- CXXMethodDecl* NewMethod = dyn_cast<CXXMethodDecl>(New);
- if (OldMethod && NewMethod &&
- !OldMethod->isStatic() && !NewMethod->isStatic() &&
- OldMethod->getTypeQualifiers() != NewMethod->getTypeQualifiers())
- return true;
+ FunctionProtoType* OldType = cast<FunctionProtoType>(OldQType);
+ FunctionProtoType* NewType = cast<FunctionProtoType>(NewQType);
+
+ // The signature of a function includes the types of its
+ // parameters (C++ 1.3.10), which includes the presence or absence
+ // of the ellipsis; see C++ DR 357).
+ if (OldQType != NewQType &&
+ (OldType->getNumArgs() != NewType->getNumArgs() ||
+ OldType->isVariadic() != NewType->isVariadic() ||
+ !std::equal(OldType->arg_type_begin(), OldType->arg_type_end(),
+ NewType->arg_type_begin())))
+ return true;
- // The signatures match; this is not an overload.
- return false;
- } else {
- // (C++ 13p1):
- // Only function declarations can be overloaded; object and type
- // declarations cannot be overloaded.
- return false;
- }
+ // C++ [temp.over.link]p4:
+ // The signature of a function template consists of its function
+ // signature, its return type and its template parameter list. The names
+ // of the template parameters are significant only for establishing the
+ // relationship between the template parameters and the rest of the
+ // signature.
+ //
+ // We check the return type and template parameter lists for function
+ // templates first; the remaining checks follow.
+ if (NewTemplate &&
+ (!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),
+ OldTemplate->getTemplateParameters(),
+ false, TPL_TemplateMatch) ||
+ OldType->getResultType() != NewType->getResultType()))
+ return true;
+
+ // If the function is a class member, its signature includes the
+ // cv-qualifiers (if any) on the function itself.
+ //
+ // As part of this, also check whether one of the member functions
+ // is static, in which case they are not overloads (C++
+ // 13.1p2). While not part of the definition of the signature,
+ // this check is important to determine whether these functions
+ // can be overloaded.
+ CXXMethodDecl* OldMethod = dyn_cast<CXXMethodDecl>(Old);
+ CXXMethodDecl* NewMethod = dyn_cast<CXXMethodDecl>(New);
+ if (OldMethod && NewMethod &&
+ !OldMethod->isStatic() && !NewMethod->isStatic() &&
+ OldMethod->getTypeQualifiers() != NewMethod->getTypeQualifiers())
+ return true;
+
+ // The signatures match; this is not an overload.
+ return false;
}
/// TryImplicitConversion - Attempt to perform an implicit conversion
@@ -1545,18 +1547,23 @@ Sema::OverloadingResult Sema::IsUserDefinedConversion(
}
bool
-Sema::DiagnoseAmbiguousUserDefinedConversion(Expr *From, QualType ToType) {
+Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) {
ImplicitConversionSequence ICS;
OverloadCandidateSet CandidateSet;
OverloadingResult OvResult =
IsUserDefinedConversion(From, ToType, ICS.UserDefined,
CandidateSet, true, false, false);
- if (OvResult != OR_Ambiguous)
+ if (OvResult == OR_Ambiguous)
+ Diag(From->getSourceRange().getBegin(),
+ diag::err_typecheck_ambiguous_condition)
+ << From->getType() << ToType << From->getSourceRange();
+ else if (OvResult == OR_No_Viable_Function && !CandidateSet.empty())
+ Diag(From->getSourceRange().getBegin(),
+ diag::err_typecheck_nonviable_condition)
+ << From->getType() << ToType << From->getSourceRange();
+ else
return false;
- Diag(From->getSourceRange().getBegin(),
- diag::err_typecheck_ambiguous_condition)
- << From->getType() << ToType << From->getSourceRange();
- PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false);
+ PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false);
return true;
}
@@ -2072,7 +2079,7 @@ bool Sema::PerformCopyInitialization(Expr *&From, QualType ToType,
if (!PerformImplicitConversion(From, ToType, Flavor,
/*AllowExplicit=*/false, Elidable))
return false;
- if (!DiagnoseAmbiguousUserDefinedConversion(From, ToType))
+ if (!DiagnoseMultipleUserDefinedConversion(From, ToType))
return Diag(From->getSourceRange().getBegin(),
diag::err_typecheck_convert_incompatible)
<< ToType << From->getType() << Flavor << From->getSourceRange();
@@ -2085,8 +2092,11 @@ bool Sema::PerformCopyInitialization(Expr *&From, QualType ToType,
ImplicitConversionSequence
Sema::TryObjectArgumentInitialization(Expr *From, CXXMethodDecl *Method) {
QualType ClassType = Context.getTypeDeclType(Method->getParent());
- QualType ImplicitParamType
- = Context.getCVRQualifiedType(ClassType, Method->getTypeQualifiers());
+ // [class.dtor]p2: A destructor can be invoked for a const, volatile or
+ // const volatile object.
+ unsigned Quals = isa<CXXDestructorDecl>(Method) ?
+ Qualifiers::Const | Qualifiers::Volatile : Method->getTypeQualifiers();
+ QualType ImplicitParamType = Context.getCVRQualifiedType(ClassType, Quals);
// Set up the conversion sequence as a "bad" conversion, to allow us
// to exit early.
@@ -2101,7 +2111,7 @@ Sema::TryObjectArgumentInitialization(Expr *From, CXXMethodDecl *Method) {
assert(FromType->isRecordType());
- // The implicit object parmeter is has the type "reference to cv X",
+ // The implicit object parameter is has the type "reference to cv X",
// where X is the class of which the function is a member
// (C++ [over.match.funcs]p4). However, when finding an implicit
// conversion sequence for the argument, we are not allowed to
@@ -2192,7 +2202,7 @@ bool Sema::PerformContextuallyConvertToBool(Expr *&From) {
if (!PerformImplicitConversion(From, Context.BoolTy, ICS, "converting"))
return false;
- if (!DiagnoseAmbiguousUserDefinedConversion(From, Context.BoolTy))
+ if (!DiagnoseMultipleUserDefinedConversion(From, Context.BoolTy))
return Diag(From->getSourceRange().getBegin(),
diag::err_typecheck_bool_condition)
<< From->getType() << From->getSourceRange();
@@ -3017,6 +3027,12 @@ BuiltinCandidateTypeSet::AddPointerWithMoreQualifiedTypeVariants(QualType Ty,
assert(PointerTy && "type was not a pointer type!");
QualType PointeeTy = PointerTy->getPointeeType();
+ // Don't add qualified variants of arrays. For one, they're not allowed
+ // (the qualifier would sink to the element type), and for another, the
+ // only overload situation where it matters is subscript or pointer +- int,
+ // and those shouldn't have qualifier variants anyway.
+ if (PointeeTy->isArrayType())
+ return true;
unsigned BaseCVR = PointeeTy.getCVRQualifiers();
if (const ConstantArrayType *Array =Context.getAsConstantArrayType(PointeeTy))
BaseCVR = Array->getElementType().getCVRQualifiers();
@@ -3057,6 +3073,12 @@ BuiltinCandidateTypeSet::AddMemberPointerWithMoreQualifiedTypeVariants(
assert(PointerTy && "type was not a member pointer type!");
QualType PointeeTy = PointerTy->getPointeeType();
+ // Don't add qualified variants of arrays. For one, they're not allowed
+ // (the qualifier would sink to the element type), and for another, the
+ // only overload situation where it matters is subscript or pointer +- int,
+ // and those shouldn't have qualifier variants anyway.
+ if (PointeeTy->isArrayType())
+ return true;
const Type *ClassTy = PointerTy->getClass();
// Iterate through all strict supersets of the pointee type's CVR
@@ -4873,11 +4895,13 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
if (Opc == BinaryOperator::PtrMemD)
return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]);
- // If this is one of the assignment operators, we only perform
- // overload resolution if the left-hand side is a class or
- // enumeration type (C++ [expr.ass]p3).
- if (Opc >= BinaryOperator::Assign && Opc <= BinaryOperator::OrAssign &&
- !Args[0]->getType()->isOverloadableType())
+ // If this is the assignment operator, we only perform overload resolution
+ // if the left-hand side is a class or enumeration type. This is actually
+ // a hack. The standard requires that we do overload resolution between the
+ // various built-in candidates, but as DR507 points out, this can lead to
+ // problems. So we do it this way, which pretty much follows what GCC does.
+ // Note that we go the traditional code path for compound assignment forms.
+ if (Opc==BinaryOperator::Assign && !Args[0]->getType()->isOverloadableType())
return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]);
// Build an empty overload set.
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 466a0e37d49c..31cd30083ed4 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -3538,15 +3538,17 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
const TemplateArgumentLoc *ExplicitTemplateArgs,
unsigned NumExplicitTemplateArgs,
SourceLocation RAngleLoc,
- NamedDecl *&PrevDecl) {
+ LookupResult &Previous) {
// The set of function template specializations that could match this
// explicit function template specialization.
typedef llvm::SmallVector<FunctionDecl *, 8> CandidateSet;
CandidateSet Candidates;
DeclContext *FDLookupContext = FD->getDeclContext()->getLookupContext();
- for (OverloadIterator Ovl(PrevDecl), OvlEnd; Ovl != OvlEnd; ++Ovl) {
- if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(*Ovl)) {
+ for (LookupResult::iterator I = Previous.begin(), E = Previous.end();
+ I != E; ++I) {
+ NamedDecl *Ovl = (*I)->getUnderlyingDecl();
+ if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(Ovl)) {
// Only consider templates found within the same semantic lookup scope as
// FD.
if (!FDLookupContext->Equals(Ovl->getDeclContext()->getLookupContext()))
@@ -3637,7 +3639,8 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
// The "previous declaration" for this function template specialization is
// the prior function template specialization.
- PrevDecl = Specialization;
+ Previous.clear();
+ Previous.addDecl(Specialization);
return false;
}
@@ -3652,10 +3655,11 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
/// \param Member the member declaration, which will be updated to become a
/// specialization.
///
-/// \param PrevDecl the set of declarations, one of which may be specialized
-/// by this function specialization.
+/// \param Previous the set of declarations, one of which may be specialized
+/// by this function specialization; the set will be modified to contain the
+/// redeclared member.
bool
-Sema::CheckMemberSpecialization(NamedDecl *Member, NamedDecl *&PrevDecl) {
+Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) {
assert(!isa<TemplateDecl>(Member) && "Only for non-template members");
// Try to find the member we are instantiating.
@@ -3663,11 +3667,13 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, NamedDecl *&PrevDecl) {
NamedDecl *InstantiatedFrom = 0;
MemberSpecializationInfo *MSInfo = 0;
- if (!PrevDecl) {
+ if (Previous.empty()) {
// Nowhere to look anyway.
} else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Member)) {
- for (OverloadIterator Ovl(PrevDecl), OvlEnd; Ovl != OvlEnd; ++Ovl) {
- if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(*Ovl)) {
+ for (LookupResult::iterator I = Previous.begin(), E = Previous.end();
+ I != E; ++I) {
+ NamedDecl *D = (*I)->getUnderlyingDecl();
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
if (Context.hasSameType(Function->getType(), Method->getType())) {
Instantiation = Method;
InstantiatedFrom = Method->getInstantiatedFromMemberFunction();
@@ -3677,15 +3683,19 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, NamedDecl *&PrevDecl) {
}
}
} else if (isa<VarDecl>(Member)) {
- if (VarDecl *PrevVar = dyn_cast<VarDecl>(PrevDecl))
+ VarDecl *PrevVar;
+ if (Previous.isSingleResult() &&
+ (PrevVar = dyn_cast<VarDecl>(Previous.getFoundDecl())))
if (PrevVar->isStaticDataMember()) {
- Instantiation = PrevDecl;
+ Instantiation = PrevVar;
InstantiatedFrom = PrevVar->getInstantiatedFromStaticDataMember();
MSInfo = PrevVar->getMemberSpecializationInfo();
}
} else if (isa<RecordDecl>(Member)) {
- if (CXXRecordDecl *PrevRecord = dyn_cast<CXXRecordDecl>(PrevDecl)) {
- Instantiation = PrevDecl;
+ CXXRecordDecl *PrevRecord;
+ if (Previous.isSingleResult() &&
+ (PrevRecord = dyn_cast<CXXRecordDecl>(Previous.getFoundDecl()))) {
+ Instantiation = PrevRecord;
InstantiatedFrom = PrevRecord->getInstantiatedFromMemberClass();
MSInfo = PrevRecord->getMemberSpecializationInfo();
}
@@ -3774,7 +3784,8 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, NamedDecl *&PrevDecl) {
// Save the caller the trouble of having to figure out which declaration
// this specialization matches.
- PrevDecl = Instantiation;
+ Previous.clear();
+ Previous.addDecl(Instantiation);
return false;
}
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 7e618cd4faea..3f40ffcdc178 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -175,7 +175,10 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
// FIXME: In theory, we could have a previous declaration for variables that
// are not static data members.
bool Redeclaration = false;
- SemaRef.CheckVariableDeclaration(Var, 0, Redeclaration);
+ // FIXME: having to fake up a LookupResult is dumb.
+ LookupResult Previous(SemaRef, Var->getDeclName(), Var->getLocation(),
+ Sema::LookupOrdinaryName);
+ SemaRef.CheckVariableDeclaration(Var, Previous, Redeclaration);
if (D->isOutOfLine()) {
D->getLexicalDeclContext()->addDecl(Var);
@@ -680,27 +683,24 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {
bool Redeclaration = false;
bool OverloadableAttrRequired = false;
- NamedDecl *PrevDecl = 0;
+ LookupResult Previous(SemaRef, Function->getDeclName(), SourceLocation(),
+ Sema::LookupOrdinaryName, Sema::ForRedeclaration);
+
if (TemplateParams || !FunctionTemplate) {
// Look only into the namespace where the friend would be declared to
// find a previous declaration. This is the innermost enclosing namespace,
// as described in ActOnFriendFunctionDecl.
- LookupResult R(SemaRef, Function->getDeclName(), SourceLocation(),
- Sema::LookupOrdinaryName,
- Sema::ForRedeclaration);
- SemaRef.LookupQualifiedName(R, DC);
+ SemaRef.LookupQualifiedName(Previous, DC);
- PrevDecl = R.getAsSingleDecl(SemaRef.Context);
-
// In C++, the previous declaration we find might be a tag type
// (class or enum). In this case, the new declaration will hide the
// tag type. Note that this does does not apply if we're declaring a
// typedef (C++ [dcl.typedef]p4).
- if (PrevDecl && PrevDecl->getIdentifierNamespace() == Decl::IDNS_Tag)
- PrevDecl = 0;
+ if (Previous.isSingleTagDecl())
+ Previous.clear();
}
- SemaRef.CheckFunctionDeclaration(Function, PrevDecl, false, Redeclaration,
+ SemaRef.CheckFunctionDeclaration(Function, Previous, false, Redeclaration,
/*FIXME:*/OverloadableAttrRequired);
// If the original function was part of a friend declaration,
@@ -709,6 +709,7 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {
= TemplateParams? cast<NamedDecl>(D->getDescribedFunctionTemplate()) : D;
if (FromFriendD->getFriendObjectKind()) {
NamedDecl *ToFriendD = 0;
+ NamedDecl *PrevDecl;
if (TemplateParams) {
ToFriendD = cast<NamedDecl>(FunctionTemplate);
PrevDecl = FunctionTemplate->getPreviousDeclaration();
@@ -843,32 +844,31 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
if (InitMethodInstantiation(Method, D))
Method->setInvalidDecl();
- NamedDecl *PrevDecl = 0;
+ LookupResult Previous(SemaRef, Name, SourceLocation(),
+ Sema::LookupOrdinaryName, Sema::ForRedeclaration);
if (!FunctionTemplate || TemplateParams) {
- LookupResult R(SemaRef, Name, SourceLocation(),
- Sema::LookupOrdinaryName,
- Sema::ForRedeclaration);
- SemaRef.LookupQualifiedName(R, Owner);
- PrevDecl = R.getAsSingleDecl(SemaRef.Context);
+ SemaRef.LookupQualifiedName(Previous, Owner);
// In C++, the previous declaration we find might be a tag type
// (class or enum). In this case, the new declaration will hide the
// tag type. Note that this does does not apply if we're declaring a
// typedef (C++ [dcl.typedef]p4).
- if (PrevDecl && PrevDecl->getIdentifierNamespace() == Decl::IDNS_Tag)
- PrevDecl = 0;
+ if (Previous.isSingleTagDecl())
+ Previous.clear();
}
bool Redeclaration = false;
bool OverloadableAttrRequired = false;
- SemaRef.CheckFunctionDeclaration(Method, PrevDecl, false, Redeclaration,
+ SemaRef.CheckFunctionDeclaration(Method, Previous, false, Redeclaration,
/*FIXME:*/OverloadableAttrRequired);
- if (!FunctionTemplate && (!Method->isInvalidDecl() || !PrevDecl) &&
+ if (!FunctionTemplate && (!Method->isInvalidDecl() || Previous.empty()) &&
!Method->getFriendObjectKind())
Owner->addDecl(Method);
+ SemaRef.AddOverriddenMethods(Record, Method);
+
return Method;
}
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 2bee32aa0fc8..ca680c279bdb 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -3037,18 +3037,21 @@ TreeTransform<Derived>::TransformCompoundStmt(CompoundStmt *S,
template<typename Derived>
Sema::OwningStmtResult
TreeTransform<Derived>::TransformCaseStmt(CaseStmt *S) {
- // The case value expressions are not potentially evaluated.
- EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
+ OwningExprResult LHS(SemaRef), RHS(SemaRef);
+ {
+ // The case value expressions are not potentially evaluated.
+ EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
- // Transform the left-hand case value.
- OwningExprResult LHS = getDerived().TransformExpr(S->getLHS());
- if (LHS.isInvalid())
- return SemaRef.StmtError();
+ // Transform the left-hand case value.
+ LHS = getDerived().TransformExpr(S->getLHS());
+ if (LHS.isInvalid())
+ return SemaRef.StmtError();
- // Transform the right-hand case value (for the GNU case-range extension).
- OwningExprResult RHS = getDerived().TransformExpr(S->getRHS());
- if (RHS.isInvalid())
- return SemaRef.StmtError();
+ // Transform the right-hand case value (for the GNU case-range extension).
+ RHS = getDerived().TransformExpr(S->getRHS());
+ if (RHS.isInvalid())
+ return SemaRef.StmtError();
+ }
// Build the case statement.
// Case statements are always rebuilt so that they will attached to their