| //===--- SemaDecl.cpp - Semantic Analysis for Declarations ----------------===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file implements semantic analysis for declarations. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "clang/Sema/SemaInternal.h" |
| #include "clang/Sema/Initialization.h" |
| #include "clang/Sema/Lookup.h" |
| #include "clang/Sema/CXXFieldCollector.h" |
| #include "clang/Sema/Scope.h" |
| #include "clang/Sema/ScopeInfo.h" |
| #include "TypeLocBuilder.h" |
| #include "clang/AST/ASTConsumer.h" |
| #include "clang/AST/ASTContext.h" |
| #include "clang/AST/CXXInheritance.h" |
| #include "clang/AST/CommentDiagnostic.h" |
| #include "clang/AST/DeclCXX.h" |
| #include "clang/AST/DeclObjC.h" |
| #include "clang/AST/DeclTemplate.h" |
| #include "clang/AST/EvaluatedExprVisitor.h" |
| #include "clang/AST/ExprCXX.h" |
| #include "clang/AST/StmtCXX.h" |
| #include "clang/AST/CharUnits.h" |
| #include "clang/Sema/DeclSpec.h" |
| #include "clang/Sema/ParsedTemplate.h" |
| #include "clang/Parse/ParseDiagnostic.h" |
| #include "clang/Basic/PartialDiagnostic.h" |
| #include "clang/Sema/DelayedDiagnostic.h" |
| #include "clang/Basic/SourceManager.h" |
| #include "clang/Basic/TargetInfo.h" |
| // FIXME: layering (ideally, Sema shouldn't be dependent on Lex API's) |
| #include "clang/Lex/Preprocessor.h" |
| #include "clang/Lex/HeaderSearch.h" |
| #include "clang/Lex/ModuleLoader.h" |
| #include "llvm/ADT/SmallString.h" |
| #include "llvm/ADT/Triple.h" |
| #include <algorithm> |
| #include <cstring> |
| #include <functional> |
| using namespace clang; |
| using namespace sema; |
| |
| Sema::DeclGroupPtrTy Sema::ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType) { |
| if (OwnedType) { |
| Decl *Group[2] = { OwnedType, Ptr }; |
| return DeclGroupPtrTy::make(DeclGroupRef::Create(Context, Group, 2)); |
| } |
| |
| return DeclGroupPtrTy::make(DeclGroupRef(Ptr)); |
| } |
| |
| namespace { |
| |
| class TypeNameValidatorCCC : public CorrectionCandidateCallback { |
| public: |
| TypeNameValidatorCCC(bool AllowInvalid, bool WantClass=false) |
| : AllowInvalidDecl(AllowInvalid), WantClassName(WantClass) { |
| WantExpressionKeywords = false; |
| WantCXXNamedCasts = false; |
| WantRemainingKeywords = false; |
| } |
| |
| virtual bool ValidateCandidate(const TypoCorrection &candidate) { |
| if (NamedDecl *ND = candidate.getCorrectionDecl()) |
| return (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) && |
| (AllowInvalidDecl || !ND->isInvalidDecl()); |
| else |
| return !WantClassName && candidate.isKeyword(); |
| } |
| |
| private: |
| bool AllowInvalidDecl; |
| bool WantClassName; |
| }; |
| |
| } |
| |
| /// \brief Determine whether the token kind starts a simple-type-specifier. |
| bool Sema::isSimpleTypeSpecifier(tok::TokenKind Kind) const { |
| switch (Kind) { |
| // FIXME: Take into account the current language when deciding whether a |
| // token kind is a valid type specifier |
| case tok::kw_short: |
| case tok::kw_long: |
| case tok::kw___int64: |
| case tok::kw___int128: |
| case tok::kw_signed: |
| case tok::kw_unsigned: |
| case tok::kw_void: |
| case tok::kw_char: |
| case tok::kw_int: |
| case tok::kw_half: |
| case tok::kw_float: |
| case tok::kw_double: |
| case tok::kw_wchar_t: |
| case tok::kw_bool: |
| case tok::kw___underlying_type: |
| return true; |
| |
| case tok::annot_typename: |
| case tok::kw_char16_t: |
| case tok::kw_char32_t: |
| case tok::kw_typeof: |
| case tok::kw_decltype: |
| return getLangOpts().CPlusPlus; |
| |
| default: |
| break; |
| } |
| |
| return false; |
| } |
| |
| /// \brief If the identifier refers to a type name within this scope, |
| /// return the declaration of that type. |
| /// |
| /// This routine performs ordinary name lookup of the identifier II |
| /// within the given scope, with optional C++ scope specifier SS, to |
| /// determine whether the name refers to a type. If so, returns an |
| /// opaque pointer (actually a QualType) corresponding to that |
| /// type. Otherwise, returns NULL. |
| /// |
| /// If name lookup results in an ambiguity, this routine will complain |
| /// and then return NULL. |
| ParsedType Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, |
| Scope *S, CXXScopeSpec *SS, |
| bool isClassName, bool HasTrailingDot, |
| ParsedType ObjectTypePtr, |
| bool IsCtorOrDtorName, |
| bool WantNontrivialTypeSourceInfo, |
| IdentifierInfo **CorrectedII) { |
| // Determine where we will perform name lookup. |
| DeclContext *LookupCtx = 0; |
| if (ObjectTypePtr) { |
| QualType ObjectType = ObjectTypePtr.get(); |
| if (ObjectType->isRecordType()) |
| LookupCtx = computeDeclContext(ObjectType); |
| } else if (SS && SS->isNotEmpty()) { |
| LookupCtx = computeDeclContext(*SS, false); |
| |
| if (!LookupCtx) { |
| if (isDependentScopeSpecifier(*SS)) { |
| // C++ [temp.res]p3: |
| // A qualified-id that refers to a type and in which the |
| // nested-name-specifier depends on a template-parameter (14.6.2) |
| // shall be prefixed by the keyword typename to indicate that the |
| // qualified-id denotes a type, forming an |
| // elaborated-type-specifier (7.1.5.3). |
| // |
| // We therefore do not perform any name lookup if the result would |
| // refer to a member of an unknown specialization. |
| if (!isClassName && !IsCtorOrDtorName) |
| return ParsedType(); |
| |
| // We know from the grammar that this name refers to a type, |
| // so build a dependent node to describe the type. |
| if (WantNontrivialTypeSourceInfo) |
| return ActOnTypenameType(S, SourceLocation(), *SS, II, NameLoc).get(); |
| |
| NestedNameSpecifierLoc QualifierLoc = SS->getWithLocInContext(Context); |
| QualType T = |
| CheckTypenameType(ETK_None, SourceLocation(), QualifierLoc, |
| II, NameLoc); |
| |
| return ParsedType::make(T); |
| } |
| |
| return ParsedType(); |
| } |
| |
| if (!LookupCtx->isDependentContext() && |
| RequireCompleteDeclContext(*SS, LookupCtx)) |
| return ParsedType(); |
| } |
| |
| // FIXME: LookupNestedNameSpecifierName isn't the right kind of |
| // lookup for class-names. |
| LookupNameKind Kind = isClassName ? LookupNestedNameSpecifierName : |
| LookupOrdinaryName; |
| LookupResult Result(*this, &II, NameLoc, Kind); |
| if (LookupCtx) { |
| // Perform "qualified" name lookup into the declaration context we |
| // computed, which is either the type of the base of a member access |
| // expression or the declaration context associated with a prior |
| // nested-name-specifier. |
| LookupQualifiedName(Result, LookupCtx); |
| |
| if (ObjectTypePtr && Result.empty()) { |
| // C++ [basic.lookup.classref]p3: |
| // If the unqualified-id is ~type-name, the type-name is looked up |
| // in the context of the entire postfix-expression. If the type T of |
| // the object expression is of a class type C, the type-name is also |
| // looked up in the scope of class C. At least one of the lookups shall |
| // find a name that refers to (possibly cv-qualified) T. |
| LookupName(Result, S); |
| } |
| } else { |
| // Perform unqualified name lookup. |
| LookupName(Result, S); |
| } |
| |
| NamedDecl *IIDecl = 0; |
| switch (Result.getResultKind()) { |
| case LookupResult::NotFound: |
| case LookupResult::NotFoundInCurrentInstantiation: |
| if (CorrectedII) { |
| TypeNameValidatorCCC Validator(true, isClassName); |
| TypoCorrection Correction = CorrectTypo(Result.getLookupNameInfo(), |
| Kind, S, SS, Validator); |
| IdentifierInfo *NewII = Correction.getCorrectionAsIdentifierInfo(); |
| TemplateTy Template; |
| bool MemberOfUnknownSpecialization; |
| UnqualifiedId TemplateName; |
| TemplateName.setIdentifier(NewII, NameLoc); |
| NestedNameSpecifier *NNS = Correction.getCorrectionSpecifier(); |
| CXXScopeSpec NewSS, *NewSSPtr = SS; |
| if (SS && NNS) { |
| NewSS.MakeTrivial(Context, NNS, SourceRange(NameLoc)); |
| NewSSPtr = &NewSS; |
| } |
| if (Correction && (NNS || NewII != &II) && |
| // Ignore a correction to a template type as the to-be-corrected |
| // identifier is not a template (typo correction for template names |
| // is handled elsewhere). |
| !(getLangOpts().CPlusPlus && NewSSPtr && |
| isTemplateName(S, *NewSSPtr, false, TemplateName, ParsedType(), |
| false, Template, MemberOfUnknownSpecialization))) { |
| ParsedType Ty = getTypeName(*NewII, NameLoc, S, NewSSPtr, |
| isClassName, HasTrailingDot, ObjectTypePtr, |
| IsCtorOrDtorName, |
| WantNontrivialTypeSourceInfo); |
| if (Ty) { |
| std::string CorrectedStr(Correction.getAsString(getLangOpts())); |
| std::string CorrectedQuotedStr( |
| Correction.getQuoted(getLangOpts())); |
| Diag(NameLoc, diag::err_unknown_type_or_class_name_suggest) |
| << Result.getLookupName() << CorrectedQuotedStr << isClassName |
| << FixItHint::CreateReplacement(SourceRange(NameLoc), |
| CorrectedStr); |
| if (NamedDecl *FirstDecl = Correction.getCorrectionDecl()) |
| Diag(FirstDecl->getLocation(), diag::note_previous_decl) |
| << CorrectedQuotedStr; |
| |
| if (SS && NNS) |
| SS->MakeTrivial(Context, NNS, SourceRange(NameLoc)); |
| *CorrectedII = NewII; |
| return Ty; |
| } |
| } |
| } |
| // If typo correction failed or was not performed, fall through |
| case LookupResult::FoundOverloaded: |
| case LookupResult::FoundUnresolvedValue: |
| Result.suppressDiagnostics(); |
| return ParsedType(); |
| |
| case LookupResult::Ambiguous: |
| // Recover from type-hiding ambiguities by hiding the type. We'll |
| // do the lookup again when looking for an object, and we can |
| // diagnose the error then. If we don't do this, then the error |
| // about hiding the type will be immediately followed by an error |
| // that only makes sense if the identifier was treated like a type. |
| if (Result.getAmbiguityKind() == LookupResult::AmbiguousTagHiding) { |
| Result.suppressDiagnostics(); |
| return ParsedType(); |
| } |
| |
| // Look to see if we have a type anywhere in the list of results. |
| for (LookupResult::iterator Res = Result.begin(), ResEnd = Result.end(); |
| Res != ResEnd; ++Res) { |
| if (isa<TypeDecl>(*Res) || isa<ObjCInterfaceDecl>(*Res)) { |
| if (!IIDecl || |
| (*Res)->getLocation().getRawEncoding() < |
| IIDecl->getLocation().getRawEncoding()) |
| IIDecl = *Res; |
| } |
| } |
| |
| if (!IIDecl) { |
| // None of the entities we found is a type, so there is no way |
| // to even assume that the result is a type. In this case, don't |
| // complain about the ambiguity. The parser will either try to |
| // perform this lookup again (e.g., as an object name), which |
| // will produce the ambiguity, or will complain that it expected |
| // a type name. |
| Result.suppressDiagnostics(); |
| return ParsedType(); |
| } |
| |
| // We found a type within the ambiguous lookup; diagnose the |
| // ambiguity and then return that type. This might be the right |
| // answer, or it might not be, but it suppresses any attempt to |
| // perform the name lookup again. |
| break; |
| |
| case LookupResult::Found: |
| IIDecl = Result.getFoundDecl(); |
| break; |
| } |
| |
| assert(IIDecl && "Didn't find decl"); |
| |
| QualType T; |
| if (TypeDecl *TD = dyn_cast<TypeDecl>(IIDecl)) { |
| DiagnoseUseOfDecl(IIDecl, NameLoc); |
| |
| if (T.isNull()) |
| T = Context.getTypeDeclType(TD); |
| |
| // NOTE: avoid constructing an ElaboratedType(Loc) if this is a |
| // constructor or destructor name (in such a case, the scope specifier |
| // will be attached to the enclosing Expr or Decl node). |
| if (SS && SS->isNotEmpty() && !IsCtorOrDtorName) { |
| if (WantNontrivialTypeSourceInfo) { |
| // Construct a type with type-source information. |
| TypeLocBuilder Builder; |
| Builder.pushTypeSpec(T).setNameLoc(NameLoc); |
| |
| T = getElaboratedType(ETK_None, *SS, T); |
| ElaboratedTypeLoc ElabTL = Builder.push<ElaboratedTypeLoc>(T); |
| ElabTL.setElaboratedKeywordLoc(SourceLocation()); |
| ElabTL.setQualifierLoc(SS->getWithLocInContext(Context)); |
| return CreateParsedType(T, Builder.getTypeSourceInfo(Context, T)); |
| } else { |
| T = getElaboratedType(ETK_None, *SS, T); |
| } |
| } |
| } else if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(IIDecl)) { |
| (void)DiagnoseUseOfDecl(IDecl, NameLoc); |
| if (!HasTrailingDot) |
| T = Context.getObjCInterfaceType(IDecl); |
| } |
| |
| if (T.isNull()) { |
| // If it's not plausibly a type, suppress diagnostics. |
| Result.suppressDiagnostics(); |
| return ParsedType(); |
| } |
| return ParsedType::make(T); |
| } |
| |
| /// isTagName() - This method is called *for error recovery purposes only* |
| /// to determine if the specified name is a valid tag name ("struct foo"). If |
| /// so, this returns the TST for the tag corresponding to it (TST_enum, |
| /// TST_union, TST_struct, TST_interface, TST_class). This is used to diagnose |
| /// cases in C where the user forgot to specify the tag. |
| DeclSpec::TST Sema::isTagName(IdentifierInfo &II, Scope *S) { |
| // Do a tag name lookup in this scope. |
| LookupResult R(*this, &II, SourceLocation(), LookupTagName); |
| LookupName(R, S, false); |
| R.suppressDiagnostics(); |
| if (R.getResultKind() == LookupResult::Found) |
| if (const TagDecl *TD = R.getAsSingle<TagDecl>()) { |
| switch (TD->getTagKind()) { |
| case TTK_Struct: return DeclSpec::TST_struct; |
| case TTK_Interface: return DeclSpec::TST_interface; |
| case TTK_Union: return DeclSpec::TST_union; |
| case TTK_Class: return DeclSpec::TST_class; |
| case TTK_Enum: return DeclSpec::TST_enum; |
| } |
| } |
| |
| return DeclSpec::TST_unspecified; |
| } |
| |
| /// isMicrosoftMissingTypename - In Microsoft mode, within class scope, |
| /// if a CXXScopeSpec's type is equal to the type of one of the base classes |
| /// then downgrade the missing typename error to a warning. |
| /// This is needed for MSVC compatibility; Example: |
| /// @code |
| /// template<class T> class A { |
| /// public: |
| /// typedef int TYPE; |
| /// }; |
| /// template<class T> class B : public A<T> { |
| /// public: |
| /// A<T>::TYPE a; // no typename required because A<T> is a base class. |
| /// }; |
| /// @endcode |
| bool Sema::isMicrosoftMissingTypename(const CXXScopeSpec *SS, Scope *S) { |
| if (CurContext->isRecord()) { |
| const Type *Ty = SS->getScopeRep()->getAsType(); |
| |
| CXXRecordDecl *RD = cast<CXXRecordDecl>(CurContext); |
| for (CXXRecordDecl::base_class_const_iterator Base = RD->bases_begin(), |
| BaseEnd = RD->bases_end(); Base != BaseEnd; ++Base) |
| if (Context.hasSameUnqualifiedType(QualType(Ty, 1), Base->getType())) |
| return true; |
| return S->isFunctionPrototypeScope(); |
| } |
| return CurContext->isFunctionOrMethod() || S->isFunctionPrototypeScope(); |
| } |
| |
| bool Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II, |
| SourceLocation IILoc, |
| Scope *S, |
| CXXScopeSpec *SS, |
| ParsedType &SuggestedType) { |
| // We don't have anything to suggest (yet). |
| SuggestedType = ParsedType(); |
| |
| // There may have been a typo in the name of the type. Look up typo |
| // results, in case we have something that we can suggest. |
| TypeNameValidatorCCC Validator(false); |
| if (TypoCorrection Corrected = CorrectTypo(DeclarationNameInfo(II, IILoc), |
| LookupOrdinaryName, S, SS, |
| Validator)) { |
| std::string CorrectedStr(Corrected.getAsString(getLangOpts())); |
| std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOpts())); |
| |
| if (Corrected.isKeyword()) { |
| // We corrected to a keyword. |
| IdentifierInfo *NewII = Corrected.getCorrectionAsIdentifierInfo(); |
| if (!isSimpleTypeSpecifier(NewII->getTokenID())) |
| CorrectedQuotedStr = "the keyword " + CorrectedQuotedStr; |
| Diag(IILoc, diag::err_unknown_typename_suggest) |
| << II << CorrectedQuotedStr |
| << FixItHint::CreateReplacement(SourceRange(IILoc), CorrectedStr); |
| II = NewII; |
| } else { |
| NamedDecl *Result = Corrected.getCorrectionDecl(); |
| // We found a similarly-named type or interface; suggest that. |
| if (!SS || !SS->isSet()) |
| Diag(IILoc, diag::err_unknown_typename_suggest) |
| << II << CorrectedQuotedStr |
| << FixItHint::CreateReplacement(SourceRange(IILoc), CorrectedStr); |
| else if (DeclContext *DC = computeDeclContext(*SS, false)) |
| Diag(IILoc, diag::err_unknown_nested_typename_suggest) |
| << II << DC << CorrectedQuotedStr << SS->getRange() |
| << FixItHint::CreateReplacement(SourceRange(IILoc), CorrectedStr); |
| else |
| llvm_unreachable("could not have corrected a typo here"); |
| |
| Diag(Result->getLocation(), diag::note_previous_decl) |
| << CorrectedQuotedStr; |
| |
| SuggestedType = getTypeName(*Result->getIdentifier(), IILoc, S, SS, |
| false, false, ParsedType(), |
| /*IsCtorOrDtorName=*/false, |
| /*NonTrivialTypeSourceInfo=*/true); |
| } |
| return true; |
| } |
| |
| if (getLangOpts().CPlusPlus) { |
| // See if II is a class template that the user forgot to pass arguments to. |
| UnqualifiedId Name; |
| Name.setIdentifier(II, IILoc); |
| CXXScopeSpec EmptySS; |
| TemplateTy TemplateResult; |
| bool MemberOfUnknownSpecialization; |
| if (isTemplateName(S, SS ? *SS : EmptySS, /*hasTemplateKeyword=*/false, |
| Name, ParsedType(), true, TemplateResult, |
| MemberOfUnknownSpecialization) == TNK_Type_template) { |
| TemplateName TplName = TemplateResult.getAsVal<TemplateName>(); |
| Diag(IILoc, diag::err_template_missing_args) << TplName; |
| if (TemplateDecl *TplDecl = TplName.getAsTemplateDecl()) { |
| Diag(TplDecl->getLocation(), diag::note_template_decl_here) |
| << TplDecl->getTemplateParameters()->getSourceRange(); |
| } |
| return true; |
| } |
| } |
| |
| // FIXME: Should we move the logic that tries to recover from a missing tag |
| // (struct, union, enum) from Parser::ParseImplicitInt here, instead? |
| |
| if (!SS || (!SS->isSet() && !SS->isInvalid())) |
| Diag(IILoc, diag::err_unknown_typename) << II; |
| else if (DeclContext *DC = computeDeclContext(*SS, false)) |
| Diag(IILoc, diag::err_typename_nested_not_found) |
| << II << DC << SS->getRange(); |
| else if (isDependentScopeSpecifier(*SS)) { |
| unsigned DiagID = diag::err_typename_missing; |
| if (getLangOpts().MicrosoftMode && isMicrosoftMissingTypename(SS, S)) |
| DiagID = diag::warn_typename_missing; |
| |
| Diag(SS->getRange().getBegin(), DiagID) |
| << (NestedNameSpecifier *)SS->getScopeRep() << II->getName() |
| << SourceRange(SS->getRange().getBegin(), IILoc) |
| << FixItHint::CreateInsertion(SS->getRange().getBegin(), "typename "); |
| SuggestedType = ActOnTypenameType(S, SourceLocation(), |
| *SS, *II, IILoc).get(); |
| } else { |
| assert(SS && SS->isInvalid() && |
| "Invalid scope specifier has already been diagnosed"); |
| } |
| |
| return true; |
| } |
| |
| /// \brief Determine whether the given result set contains either a type name |
| /// or |
| static bool isResultTypeOrTemplate(LookupResult &R, const Token &NextToken) { |
| bool CheckTemplate = R.getSema().getLangOpts().CPlusPlus && |
| NextToken.is(tok::less); |
| |
| for (LookupResult::iterator I = R.begin(), IEnd = R.end(); I != IEnd; ++I) { |
| if (isa<TypeDecl>(*I) || isa<ObjCInterfaceDecl>(*I)) |
| return true; |
| |
| if (CheckTemplate && isa<TemplateDecl>(*I)) |
| return true; |
| } |
| |
| return false; |
| } |
| |
| static bool isTagTypeWithMissingTag(Sema &SemaRef, LookupResult &Result, |
| Scope *S, CXXScopeSpec &SS, |
| IdentifierInfo *&Name, |
| SourceLocation NameLoc) { |
| LookupResult R(SemaRef, Name, NameLoc, Sema::LookupTagName); |
| SemaRef.LookupParsedName(R, S, &SS); |
| if (TagDecl *Tag = R.getAsSingle<TagDecl>()) { |
| const char *TagName = 0; |
| const char *FixItTagName = 0; |
| switch (Tag->getTagKind()) { |
| case TTK_Class: |
| TagName = "class"; |
| FixItTagName = "class "; |
| break; |
| |
| case TTK_Enum: |
| TagName = "enum"; |
| FixItTagName = "enum "; |
| break; |
| |
| case TTK_Struct: |
| TagName = "struct"; |
| FixItTagName = "struct "; |
| break; |
| |
| case TTK_Interface: |
| TagName = "__interface"; |
| FixItTagName = "__interface "; |
| break; |
| |
| case TTK_Union: |
| TagName = "union"; |
| FixItTagName = "union "; |
| break; |
| } |
| |
| SemaRef.Diag(NameLoc, diag::err_use_of_tag_name_without_tag) |
| << Name << TagName << SemaRef.getLangOpts().CPlusPlus |
| << FixItHint::CreateInsertion(NameLoc, FixItTagName); |
| |
| for (LookupResult::iterator I = Result.begin(), IEnd = Result.end(); |
| I != IEnd; ++I) |
| SemaRef.Diag((*I)->getLocation(), diag::note_decl_hiding_tag_type) |
| << Name << TagName; |
| |
| // Replace lookup results with just the tag decl. |
| Result.clear(Sema::LookupTagName); |
| SemaRef.LookupParsedName(Result, S, &SS); |
| return true; |
| } |
| |
| return false; |
| } |
| |
| /// Build a ParsedType for a simple-type-specifier with a nested-name-specifier. |
| static ParsedType buildNestedType(Sema &S, CXXScopeSpec &SS, |
| QualType T, SourceLocation NameLoc) { |
| ASTContext &Context = S.Context; |
| |
| TypeLocBuilder Builder; |
| Builder.pushTypeSpec(T).setNameLoc(NameLoc); |
| |
| T = S.getElaboratedType(ETK_None, SS, T); |
| ElaboratedTypeLoc ElabTL = Builder.push<ElaboratedTypeLoc>(T); |
| ElabTL.setElaboratedKeywordLoc(SourceLocation()); |
| ElabTL.setQualifierLoc(SS.getWithLocInContext(Context)); |
| return S.CreateParsedType(T, Builder.getTypeSourceInfo(Context, T)); |
| } |
| |
| Sema::NameClassification Sema::ClassifyName(Scope *S, |
| CXXScopeSpec &SS, |
| IdentifierInfo *&Name, |
| SourceLocation NameLoc, |
| const Token &NextToken, |
| bool IsAddressOfOperand, |
| CorrectionCandidateCallback *CCC) { |
| DeclarationNameInfo NameInfo(Name, NameLoc); |
| ObjCMethodDecl *CurMethod = getCurMethodDecl(); |
| |
| if (NextToken.is(tok::coloncolon)) { |
| BuildCXXNestedNameSpecifier(S, *Name, NameLoc, NextToken.getLocation(), |
| QualType(), false, SS, 0, false); |
| |
| } |
| |
| LookupResult Result(*this, Name, NameLoc, LookupOrdinaryName); |
| LookupParsedName(Result, S, &SS, !CurMethod); |
| |
| // Perform lookup for Objective-C instance variables (including automatically |
| // synthesized instance variables), if we're in an Objective-C method. |
| // FIXME: This lookup really, really needs to be folded in to the normal |
| // unqualified lookup mechanism. |
| if (!SS.isSet() && CurMethod && !isResultTypeOrTemplate(Result, NextToken)) { |
| ExprResult E = LookupInObjCMethod(Result, S, Name, true); |
| if (E.get() || E.isInvalid()) |
| return E; |
| } |
| |
| bool SecondTry = false; |
| bool IsFilteredTemplateName = false; |
| |
| Corrected: |
| switch (Result.getResultKind()) { |
| case LookupResult::NotFound: |
| // If an unqualified-id is followed by a '(', then we have a function |
| // call. |
| if (!SS.isSet() && NextToken.is(tok::l_paren)) { |
| // In C++, this is an ADL-only call. |
| // FIXME: Reference? |
| if (getLangOpts().CPlusPlus) |
| return BuildDeclarationNameExpr(SS, Result, /*ADL=*/true); |
| |
| // C90 6.3.2.2: |
| // If the expression that precedes the parenthesized argument list in a |
| // function call consists solely of an identifier, and if no |
| // declaration is visible for this identifier, the identifier is |
| // implicitly declared exactly as if, in the innermost block containing |
| // the function call, the declaration |
| // |
| // extern int identifier (); |
| // |
| // appeared. |
| // |
| // We also allow this in C99 as an extension. |
| if (NamedDecl *D = ImplicitlyDefineFunction(NameLoc, *Name, S)) { |
| Result.addDecl(D); |
| Result.resolveKind(); |
| return BuildDeclarationNameExpr(SS, Result, /*ADL=*/false); |
| } |
| } |
| |
| // In C, we first see whether there is a tag type by the same name, in |
| // which case it's likely that the user just forget to write "enum", |
| // "struct", or "union". |
| if (!getLangOpts().CPlusPlus && !SecondTry && |
| isTagTypeWithMissingTag(*this, Result, S, SS, Name, NameLoc)) { |
| break; |
| } |
| |
| // Perform typo correction to determine if there is another name that is |
| // close to this name. |
| if (!SecondTry && CCC) { |
| SecondTry = true; |
| if (TypoCorrection Corrected = CorrectTypo(Result.getLookupNameInfo(), |
| Result.getLookupKind(), S, |
| &SS, *CCC)) { |
| unsigned UnqualifiedDiag = diag::err_undeclared_var_use_suggest; |
| unsigned QualifiedDiag = diag::err_no_member_suggest; |
| std::string CorrectedStr(Corrected.getAsString(getLangOpts())); |
| std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOpts())); |
| |
| NamedDecl *FirstDecl = Corrected.getCorrectionDecl(); |
| NamedDecl *UnderlyingFirstDecl |
| = FirstDecl? FirstDecl->getUnderlyingDecl() : 0; |
| if (getLangOpts().CPlusPlus && NextToken.is(tok::less) && |
| UnderlyingFirstDecl && isa<TemplateDecl>(UnderlyingFirstDecl)) { |
| UnqualifiedDiag = diag::err_no_template_suggest; |
| QualifiedDiag = diag::err_no_member_template_suggest; |
| } else if (UnderlyingFirstDecl && |
| (isa<TypeDecl>(UnderlyingFirstDecl) || |
| isa<ObjCInterfaceDecl>(UnderlyingFirstDecl) || |
| isa<ObjCCompatibleAliasDecl>(UnderlyingFirstDecl))) { |
| UnqualifiedDiag = diag::err_unknown_typename_suggest; |
| QualifiedDiag = diag::err_unknown_nested_typename_suggest; |
| } |
| |
| if (SS.isEmpty()) |
| Diag(NameLoc, UnqualifiedDiag) |
| << Name << CorrectedQuotedStr |
| << FixItHint::CreateReplacement(NameLoc, CorrectedStr); |
| else |
| Diag(NameLoc, QualifiedDiag) |
| << Name << computeDeclContext(SS, false) << CorrectedQuotedStr |
| << SS.getRange() |
| << FixItHint::CreateReplacement(NameLoc, CorrectedStr); |
| |
| // Update the name, so that the caller has the new name. |
| Name = Corrected.getCorrectionAsIdentifierInfo(); |
| |
| // Typo correction corrected to a keyword. |
| if (Corrected.isKeyword()) |
| return Corrected.getCorrectionAsIdentifierInfo(); |
| |
| // Also update the LookupResult... |
| // FIXME: This should probably go away at some point |
| Result.clear(); |
| Result.setLookupName(Corrected.getCorrection()); |
| if (FirstDecl) { |
| Result.addDecl(FirstDecl); |
| Diag(FirstDecl->getLocation(), diag::note_previous_decl) |
| << CorrectedQuotedStr; |
| } |
| |
| // If we found an Objective-C instance variable, let |
| // LookupInObjCMethod build the appropriate expression to |
| // reference the ivar. |
| // FIXME: This is a gross hack. |
| if (ObjCIvarDecl *Ivar = Result.getAsSingle<ObjCIvarDecl>()) { |
| Result.clear(); |
| ExprResult E(LookupInObjCMethod(Result, S, Ivar->getIdentifier())); |
| return E; |
| } |
| |
| goto Corrected; |
| } |
| } |
| |
| // We failed to correct; just fall through and let the parser deal with it. |
| Result.suppressDiagnostics(); |
| return NameClassification::Unknown(); |
| |
| case LookupResult::NotFoundInCurrentInstantiation: { |
| // We performed name lookup into the current instantiation, and there were |
| // dependent bases, so we treat this result the same way as any other |
| // dependent nested-name-specifier. |
| |
| // C++ [temp.res]p2: |
| // A name used in a template declaration or definition and that is |
| // dependent on a template-parameter is assumed not to name a type |
| // unless the applicable name lookup finds a type name or the name is |
| // qualified by the keyword typename. |
| // |
| // FIXME: If the next token is '<', we might want to ask the parser to |
| // perform some heroics to see if we actually have a |
| // template-argument-list, which would indicate a missing 'template' |
| // keyword here. |
| return ActOnDependentIdExpression(SS, /*TemplateKWLoc=*/SourceLocation(), |
| NameInfo, IsAddressOfOperand, |
| /*TemplateArgs=*/0); |
| } |
| |
| case LookupResult::Found: |
| case LookupResult::FoundOverloaded: |
| case LookupResult::FoundUnresolvedValue: |
| break; |
| |
| case LookupResult::Ambiguous: |
| if (getLangOpts().CPlusPlus && NextToken.is(tok::less) && |
| hasAnyAcceptableTemplateNames(Result)) { |
| // C++ [temp.local]p3: |
| // A lookup that finds an injected-class-name (10.2) can result in an |
| // ambiguity in certain cases (for example, if it is found in more than |
| // one base class). If all of the injected-class-names that are found |
| // refer to specializations of the same class template, and if the name |
| // is followed by a template-argument-list, the reference refers to the |
| // class template itself and not a specialization thereof, and is not |
| // ambiguous. |
| // |
| // This filtering can make an ambiguous result into an unambiguous one, |
| // so try again after filtering out template names. |
| FilterAcceptableTemplateNames(Result); |
| if (!Result.isAmbiguous()) { |
| IsFilteredTemplateName = true; |
| break; |
| } |
| } |
| |
| // Diagnose the ambiguity and return an error. |
| return NameClassification::Error(); |
| } |
| |
| if (getLangOpts().CPlusPlus && NextToken.is(tok::less) && |
| (IsFilteredTemplateName || hasAnyAcceptableTemplateNames(Result))) { |
| // C++ [temp.names]p3: |
| // After name lookup (3.4) finds that a name is a template-name or that |
| // an operator-function-id or a literal- operator-id refers to a set of |
| // overloaded functions any member of which is a function template if |
| // this is followed by a <, the < is always taken as the delimiter of a |
| // template-argument-list and never as the less-than operator. |
| if (!IsFilteredTemplateName) |
| FilterAcceptableTemplateNames(Result); |
| |
| if (!Result.empty()) { |
| bool IsFunctionTemplate; |
| TemplateName Template; |
| if (Result.end() - Result.begin() > 1) { |
| IsFunctionTemplate = true; |
| Template = Context.getOverloadedTemplateName(Result.begin(), |
| Result.end()); |
| } else { |
| TemplateDecl *TD |
| = cast<TemplateDecl>((*Result.begin())->getUnderlyingDecl()); |
| IsFunctionTemplate = isa<FunctionTemplateDecl>(TD); |
| |
| if (SS.isSet() && !SS.isInvalid()) |
| Template = Context.getQualifiedTemplateName(SS.getScopeRep(), |
| /*TemplateKeyword=*/false, |
| TD); |
| else |
| Template = TemplateName(TD); |
| } |
| |
| if (IsFunctionTemplate) { |
| // Function templates always go through overload resolution, at which |
| // point we'll perform the various checks (e.g., accessibility) we need |
| // to based on which function we selected. |
| Result.suppressDiagnostics(); |
| |
| return NameClassification::FunctionTemplate(Template); |
| } |
| |
| return NameClassification::TypeTemplate(Template); |
| } |
| } |
| |
| NamedDecl *FirstDecl = (*Result.begin())->getUnderlyingDecl(); |
| if (TypeDecl *Type = dyn_cast<TypeDecl>(FirstDecl)) { |
| DiagnoseUseOfDecl(Type, NameLoc); |
| QualType T = Context.getTypeDeclType(Type); |
| if (SS.isNotEmpty()) |
| return buildNestedType(*this, SS, T, NameLoc); |
| return ParsedType::make(T); |
| } |
| |
| ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(FirstDecl); |
| if (!Class) { |
| // FIXME: It's unfortunate that we don't have a Type node for handling this. |
| if (ObjCCompatibleAliasDecl *Alias |
| = dyn_cast<ObjCCompatibleAliasDecl>(FirstDecl)) |
| Class = Alias->getClassInterface(); |
| } |
| |
| if (Class) { |
| DiagnoseUseOfDecl(Class, NameLoc); |
| |
| if (NextToken.is(tok::period)) { |
| // Interface. <something> is parsed as a property reference expression. |
| // Just return "unknown" as a fall-through for now. |
| Result.suppressDiagnostics(); |
| return NameClassification::Unknown(); |
| } |
| |
| QualType T = Context.getObjCInterfaceType(Class); |
| return ParsedType::make(T); |
| } |
| |
| // We can have a type template here if we're classifying a template argument. |
| if (isa<TemplateDecl>(FirstDecl) && !isa<FunctionTemplateDecl>(FirstDecl)) |
| return NameClassification::TypeTemplate( |
| TemplateName(cast<TemplateDecl>(FirstDecl))); |
| |
| // Check for a tag type hidden by a non-type decl in a few cases where it |
| // seems likely a type is wanted instead of the non-type that was found. |
| if (!getLangOpts().ObjC1) { |
| bool NextIsOp = NextToken.is(tok::amp) || NextToken.is(tok::star); |
| if ((NextToken.is(tok::identifier) || |
| (NextIsOp && FirstDecl->isFunctionOrFunctionTemplate())) && |
| isTagTypeWithMissingTag(*this, Result, S, SS, Name, NameLoc)) { |
| TypeDecl *Type = Result.getAsSingle<TypeDecl>(); |
| DiagnoseUseOfDecl(Type, NameLoc); |
| QualType T = Context.getTypeDeclType(Type); |
| if (SS.isNotEmpty()) |
| return buildNestedType(*this, SS, T, NameLoc); |
| return ParsedType::make(T); |
| } |
| } |
| |
| if (FirstDecl->isCXXClassMember()) |
| return BuildPossibleImplicitMemberExpr(SS, SourceLocation(), Result, 0); |
| |
| bool ADL = UseArgumentDependentLookup(SS, Result, NextToken.is(tok::l_paren)); |
| return BuildDeclarationNameExpr(SS, Result, ADL); |
| } |
| |
| // Determines the context to return to after temporarily entering a |
| // context. This depends in an unnecessarily complicated way on the |
| // exact ordering of callbacks from the parser. |
| DeclContext *Sema::getContainingDC(DeclContext *DC) { |
| |
| // Functions defined inline within classes aren't parsed until we've |
| // finished parsing the top-level class, so the top-level class is |
| // the context we'll need to return to. |
| if (isa<FunctionDecl>(DC)) { |
| DC = DC->getLexicalParent(); |
| |
| // A function not defined within a class will always return to its |
| // lexical context. |
| if (!isa<CXXRecordDecl>(DC)) |
| return DC; |
| |
| // A C++ inline method/friend is parsed *after* the topmost class |
| // it was declared in is fully parsed ("complete"); the topmost |
| // class is the context we need to return to. |
| while (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC->getLexicalParent())) |
| DC = RD; |
| |
| // Return the declaration context of the topmost class the inline method is |
| // declared in. |
| return DC; |
| } |
| |
| return DC->getLexicalParent(); |
| } |
| |
| void Sema::PushDeclContext(Scope *S, DeclContext *DC) { |
| assert(getContainingDC(DC) == CurContext && |
| "The next DeclContext should be lexically contained in the current one."); |
| CurContext = DC; |
| S->setEntity(DC); |
| } |
| |
| void Sema::PopDeclContext() { |
| assert(CurContext && "DeclContext imbalance!"); |
| |
| CurContext = getContainingDC(CurContext); |
| assert(CurContext && "Popped translation unit!"); |
| } |
| |
| /// EnterDeclaratorContext - Used when we must lookup names in the context |
| /// of a declarator's nested name specifier. |
| /// |
| void Sema::EnterDeclaratorContext(Scope *S, DeclContext *DC) { |
| // C++0x [basic.lookup.unqual]p13: |
| // A name used in the definition of a static data member of class |
| // X (after the qualified-id of the static member) is looked up as |
| // if the name was used in a member function of X. |
| // C++0x [basic.lookup.unqual]p14: |
| // If a variable member of a namespace is defined outside of the |
| // scope of its namespace then any name used in the definition of |
| // the variable member (after the declarator-id) is looked up as |
| // if the definition of the variable member occurred in its |
| // namespace. |
| // Both of these imply that we should push a scope whose context |
| // is the semantic context of the declaration. We can't use |
| // PushDeclContext here because that context is not necessarily |
| // lexically contained in the current context. Fortunately, |
| // the containing scope should have the appropriate information. |
| |
| assert(!S->getEntity() && "scope already has entity"); |
| |
| #ifndef NDEBUG |
| Scope *Ancestor = S->getParent(); |
| while (!Ancestor->getEntity()) Ancestor = Ancestor->getParent(); |
| assert(Ancestor->getEntity() == CurContext && "ancestor context mismatch"); |
| #endif |
| |
| CurContext = DC; |
| S->setEntity(DC); |
| } |
| |
| void Sema::ExitDeclaratorContext(Scope *S) { |
| assert(S->getEntity() == CurContext && "Context imbalance!"); |
| |
| // Switch back to the lexical context. The safety of this is |
| // enforced by an assert in EnterDeclaratorContext. |
| Scope *Ancestor = S->getParent(); |
| while (!Ancestor->getEntity()) Ancestor = Ancestor->getParent(); |
| CurContext = (DeclContext*) Ancestor->getEntity(); |
| |
| // We don't need to do anything with the scope, which is going to |
| // disappear. |
| } |
| |
| |
| void Sema::ActOnReenterFunctionContext(Scope* S, Decl *D) { |
| FunctionDecl *FD = dyn_cast<FunctionDecl>(D); |
| if (FunctionTemplateDecl *TFD = dyn_cast_or_null<FunctionTemplateDecl>(D)) { |
| // We assume that the caller has already called |
| // ActOnReenterTemplateScope |
| FD = TFD->getTemplatedDecl(); |
| } |
| if (!FD) |
| return; |
| |
| // Same implementation as PushDeclContext, but enters the context |
| // from the lexical parent, rather than the top-level class. |
| assert(CurContext == FD->getLexicalParent() && |
| "The next DeclContext should be lexically contained in the current one."); |
| CurContext = FD; |
| S->setEntity(CurContext); |
| |
| for (unsigned P = 0, NumParams = FD->getNumParams(); P < NumParams; ++P) { |
| ParmVarDecl *Param = FD->getParamDecl(P); |
| // If the parameter has an identifier, then add it to the scope |
| if (Param->getIdentifier()) { |
| S->AddDecl(Param); |
| IdResolver.AddDecl(Param); |
| } |
| } |
| } |
| |
| |
| void Sema::ActOnExitFunctionContext() { |
| // Same implementation as PopDeclContext, but returns to the lexical parent, |
| // rather than the top-level class. |
| assert(CurContext && "DeclContext imbalance!"); |
| CurContext = CurContext->getLexicalParent(); |
| assert(CurContext && "Popped translation unit!"); |
| } |
| |
| |
| /// \brief Determine whether we allow overloading of the function |
| /// PrevDecl with another declaration. |
| /// |
| /// This routine determines whether overloading is possible, not |
| /// whether some new function is actually an overload. It will return |
| /// true in C++ (where we can always provide overloads) or, as an |
| /// extension, in C when the previous function is already an |
| /// overloaded function declaration or has the "overloadable" |
| /// attribute. |
| static bool AllowOverloadingOfFunction(LookupResult &Previous, |
| ASTContext &Context) { |
| if (Context.getLangOpts().CPlusPlus) |
| return true; |
| |
| if (Previous.getResultKind() == LookupResult::FoundOverloaded) |
| return true; |
| |
| return (Previous.getResultKind() == LookupResult::Found |
| && Previous.getFoundDecl()->hasAttr<OverloadableAttr>()); |
| } |
| |
| /// Add this decl to the scope shadowed decl chains. |
| void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) { |
| // Move up the scope chain until we find the nearest enclosing |
| // non-transparent context. The declaration will be introduced into this |
| // scope. |
| while (S->getEntity() && |
| ((DeclContext *)S->getEntity())->isTransparentContext()) |
| S = S->getParent(); |
| |
| // Add scoped declarations into their context, so that they can be |
| // found later. Declarations without a context won't be inserted |
| // into any context. |
| if (AddToContext) |
| CurContext->addDecl(D); |
| |
| // Out-of-line definitions shouldn't be pushed into scope in C++. |
| // Out-of-line variable and function definitions shouldn't even in C. |
| if ((getLangOpts().CPlusPlus || isa<VarDecl>(D) || isa<FunctionDecl>(D)) && |
| D->isOutOfLine() && |
| !D->getDeclContext()->getRedeclContext()->Equals( |
| D->getLexicalDeclContext()->getRedeclContext())) |
| return; |
| |
| // Template instantiations should also not be pushed into scope. |
| if (isa<FunctionDecl>(D) && |
| cast<FunctionDecl>(D)->isFunctionTemplateSpecialization()) |
| return; |
| |
| // If this replaces anything in the current scope, |
| IdentifierResolver::iterator I = IdResolver.begin(D->getDeclName()), |
| IEnd = IdResolver.end(); |
| for (; I != IEnd; ++I) { |
| if (S->isDeclScope(*I) && D->declarationReplaces(*I)) { |
| S->RemoveDecl(*I); |
| IdResolver.RemoveDecl(*I); |
| |
| // Should only need to replace one decl. |
| break; |
| } |
| } |
| |
| S->AddDecl(D); |
| |
| if (isa<LabelDecl>(D) && !cast<LabelDecl>(D)->isGnuLocal()) { |
| // Implicitly-generated labels may end up getting generated in an order that |
| // isn't strictly lexical, which breaks name lookup. Be careful to insert |
| // the label at the appropriate place in the identifier chain. |
| for (I = IdResolver.begin(D->getDeclName()); I != IEnd; ++I) { |
| DeclContext *IDC = (*I)->getLexicalDeclContext()->getRedeclContext(); |
| if (IDC == CurContext) { |
| if (!S->isDeclScope(*I)) |
| continue; |
| } else if (IDC->Encloses(CurContext)) |
| break; |
| } |
| |
| IdResolver.InsertDeclAfter(I, D); |
| } else { |
| IdResolver.AddDecl(D); |
| } |
| } |
| |
| void Sema::pushExternalDeclIntoScope(NamedDecl *D, DeclarationName Name) { |
| if (IdResolver.tryAddTopLevelDecl(D, Name) && TUScope) |
| TUScope->AddDecl(D); |
| } |
| |
| bool Sema::isDeclInScope(NamedDecl *&D, DeclContext *Ctx, Scope *S, |
| bool ExplicitInstantiationOrSpecialization) { |
| return IdResolver.isDeclInScope(D, Ctx, Context, S, |
| ExplicitInstantiationOrSpecialization); |
| } |
| |
| Scope *Sema::getScopeForDeclContext(Scope *S, DeclContext *DC) { |
| DeclContext *TargetDC = DC->getPrimaryContext(); |
| do { |
| if (DeclContext *ScopeDC = (DeclContext*) S->getEntity()) |
| if (ScopeDC->getPrimaryContext() == TargetDC) |
| return S; |
| } while ((S = S->getParent())); |
| |
| return 0; |
| } |
| |
| static bool isOutOfScopePreviousDeclaration(NamedDecl *, |
| DeclContext*, |
| ASTContext&); |
| |
| /// Filters out lookup results that don't fall within the given scope |
| /// as determined by isDeclInScope. |
| void Sema::FilterLookupForScope(LookupResult &R, |
| DeclContext *Ctx, Scope *S, |
| bool ConsiderLinkage, |
| bool ExplicitInstantiationOrSpecialization) { |
| LookupResult::Filter F = R.makeFilter(); |
| while (F.hasNext()) { |
| NamedDecl *D = F.next(); |
| |
| if (isDeclInScope(D, Ctx, S, ExplicitInstantiationOrSpecialization)) |
| continue; |
| |
| if (ConsiderLinkage && |
| isOutOfScopePreviousDeclaration(D, Ctx, 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(); |
| } |
| |
| /// \brief Check for this common pattern: |
| /// @code |
| /// class S { |
| /// S(const S&); // DO NOT IMPLEMENT |
| /// void operator=(const S&); // DO NOT IMPLEMENT |
| /// }; |
| /// @endcode |
| static bool IsDisallowedCopyOrAssign(const CXXMethodDecl *D) { |
| // FIXME: Should check for private access too but access is set after we get |
| // the decl here. |
| if (D->doesThisDeclarationHaveABody()) |
| return false; |
| |
| if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(D)) |
| return CD->isCopyConstructor(); |
| if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) |
| return Method->isCopyAssignmentOperator(); |
| return false; |
| } |
| |
| bool Sema::ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const { |
| assert(D); |
| |
| if (D->isInvalidDecl() || D->isUsed() || D->hasAttr<UnusedAttr>()) |
| return false; |
| |
| // Ignore class templates. |
| if (D->getDeclContext()->isDependentContext() || |
| D->getLexicalDeclContext()->isDependentContext()) |
| return false; |
| |
| if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { |
| if (FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) |
| return false; |
| |
| if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) { |
| if (MD->isVirtual() || IsDisallowedCopyOrAssign(MD)) |
| return false; |
| } else { |
| // 'static inline' functions are used in headers; don't warn. |
| if (FD->getStorageClass() == SC_Static && |
| FD->isInlineSpecified()) |
| return false; |
| } |
| |
| if (FD->doesThisDeclarationHaveABody() && |
| Context.DeclMustBeEmitted(FD)) |
| return false; |
| } else if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { |
| if (!VD->isFileVarDecl() || |
| VD->getType().isConstant(Context) || |
| Context.DeclMustBeEmitted(VD)) |
| return false; |
| |
| if (VD->isStaticDataMember() && |
| VD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) |
| return false; |
| |
| } else { |
| return false; |
| } |
| |
| // Only warn for unused decls internal to the translation unit. |
| if (D->getLinkage() == ExternalLinkage) |
| return false; |
| |
| return true; |
| } |
| |
| void Sema::MarkUnusedFileScopedDecl(const DeclaratorDecl *D) { |
| if (!D) |
| return; |
| |
| if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { |
| const FunctionDecl *First = FD->getFirstDeclaration(); |
| if (FD != First && ShouldWarnIfUnusedFileScopedDecl(First)) |
| return; // First should already be in the vector. |
| } |
| |
| if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { |
| const VarDecl *First = VD->getFirstDeclaration(); |
| if (VD != First && ShouldWarnIfUnusedFileScopedDecl(First)) |
| return; // First should already be in the vector. |
| } |
| |
| if (ShouldWarnIfUnusedFileScopedDecl(D)) |
| UnusedFileScopedDecls.push_back(D); |
| } |
| |
| static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) { |
| if (D->isInvalidDecl()) |
| return false; |
| |
| if (D->isReferenced() || D->isUsed() || D->hasAttr<UnusedAttr>()) |
| return false; |
| |
| if (isa<LabelDecl>(D)) |
| return true; |
| |
| // White-list anything that isn't a local variable. |
| if (!isa<VarDecl>(D) || isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D) || |
| !D->getDeclContext()->isFunctionOrMethod()) |
| return false; |
| |
| // Types of valid local variables should be complete, so this should succeed. |
| if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { |
| |
| // White-list anything with an __attribute__((unused)) type. |
| QualType Ty = VD->getType(); |
| |
| // Only look at the outermost level of typedef. |
| if (const TypedefType *TT = dyn_cast<TypedefType>(Ty)) { |
| if (TT->getDecl()->hasAttr<UnusedAttr>()) |
| return false; |
| } |
| |
| // If we failed to complete the type for some reason, or if the type is |
| // dependent, don't diagnose the variable. |
| if (Ty->isIncompleteType() || Ty->isDependentType()) |
| return false; |
| |
| if (const TagType *TT = Ty->getAs<TagType>()) { |
| const TagDecl *Tag = TT->getDecl(); |
| if (Tag->hasAttr<UnusedAttr>()) |
| return false; |
| |
| if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Tag)) { |
| if (!RD->hasTrivialDestructor()) |
| return false; |
| |
| if (const Expr *Init = VD->getInit()) { |
| const CXXConstructExpr *Construct = |
| dyn_cast<CXXConstructExpr>(Init); |
| if (Construct && !Construct->isElidable()) { |
| CXXConstructorDecl *CD = Construct->getConstructor(); |
| if (!CD->isTrivial()) |
| return false; |
| } |
| } |
| } |
| } |
| |
| // TODO: __attribute__((unused)) templates? |
| } |
| |
| return true; |
| } |
| |
| static void GenerateFixForUnusedDecl(const NamedDecl *D, ASTContext &Ctx, |
| FixItHint &Hint) { |
| if (isa<LabelDecl>(D)) { |
| SourceLocation AfterColon = Lexer::findLocationAfterToken(D->getLocEnd(), |
| tok::colon, Ctx.getSourceManager(), Ctx.getLangOpts(), true); |
| if (AfterColon.isInvalid()) |
| return; |
| Hint = FixItHint::CreateRemoval(CharSourceRange:: |
| getCharRange(D->getLocStart(), AfterColon)); |
| } |
| return; |
| } |
| |
| /// DiagnoseUnusedDecl - Emit warnings about declarations that are not used |
| /// unless they are marked attr(unused). |
| void Sema::DiagnoseUnusedDecl(const NamedDecl *D) { |
| FixItHint Hint; |
| if (!ShouldDiagnoseUnusedDecl(D)) |
| return; |
| |
| GenerateFixForUnusedDecl(D, Context, Hint); |
| |
| unsigned DiagID; |
| if (isa<VarDecl>(D) && cast<VarDecl>(D)->isExceptionVariable()) |
| DiagID = diag::warn_unused_exception_param; |
| else if (isa<LabelDecl>(D)) |
| DiagID = diag::warn_unused_label; |
| else |
| DiagID = diag::warn_unused_variable; |
| |
| Diag(D->getLocation(), DiagID) << D->getDeclName() << Hint; |
| } |
| |
| static void CheckPoppedLabel(LabelDecl *L, Sema &S) { |
| // Verify that we have no forward references left. If so, there was a goto |
| // or address of a label taken, but no definition of it. Label fwd |
| // definitions are indicated with a null substmt. |
| if (L->getStmt() == 0) |
| S.Diag(L->getLocation(), diag::err_undeclared_label_use) <<L->getDeclName(); |
| } |
| |
| void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { |
| if (S->decl_empty()) return; |
| assert((S->getFlags() & (Scope::DeclScope | Scope::TemplateParamScope)) && |
| "Scope shouldn't contain decls!"); |
| |
| for (Scope::decl_iterator I = S->decl_begin(), E = S->decl_end(); |
| I != E; ++I) { |
| Decl *TmpD = (*I); |
| assert(TmpD && "This decl didn't get pushed??"); |
| |
| assert(isa<NamedDecl>(TmpD) && "Decl isn't NamedDecl?"); |
| NamedDecl *D = cast<NamedDecl>(TmpD); |
| |
| if (!D->getDeclName()) continue; |
| |
| // Diagnose unused variables in this scope. |
| if (!S->hasErrorOccurred()) |
| DiagnoseUnusedDecl(D); |
| |
| // If this was a forward reference to a label, verify it was defined. |
| if (LabelDecl *LD = dyn_cast<LabelDecl>(D)) |
| CheckPoppedLabel(LD, *this); |
| |
| // Remove this name from our lexical scope. |
| IdResolver.RemoveDecl(D); |
| } |
| } |
| |
| void Sema::ActOnStartFunctionDeclarator() { |
| ++InFunctionDeclarator; |
| } |
| |
| void Sema::ActOnEndFunctionDeclarator() { |
| assert(InFunctionDeclarator); |
| --InFunctionDeclarator; |
| } |
| |
| /// \brief Look for an Objective-C class in the translation unit. |
| /// |
| /// \param Id The name of the Objective-C class we're looking for. If |
| /// typo-correction fixes this name, the Id will be updated |
| /// to the fixed name. |
| /// |
| /// \param IdLoc The location of the name in the translation unit. |
| /// |
| /// \param DoTypoCorrection If true, this routine will attempt typo correction |
| /// if there is no class with the given name. |
| /// |
| /// \returns The declaration of the named Objective-C class, or NULL if the |
| /// class could not be found. |
| ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *&Id, |
| SourceLocation IdLoc, |
| bool DoTypoCorrection) { |
| // The third "scope" argument is 0 since we aren't enabling lazy built-in |
| // creation from this context. |
| NamedDecl *IDecl = LookupSingleName(TUScope, Id, IdLoc, LookupOrdinaryName); |
| |
| if (!IDecl && DoTypoCorrection) { |
| // Perform typo correction at the given location, but only if we |
| // find an Objective-C class name. |
| DeclFilterCCC<ObjCInterfaceDecl> Validator; |
| if (TypoCorrection C = CorrectTypo(DeclarationNameInfo(Id, IdLoc), |
| LookupOrdinaryName, TUScope, NULL, |
| Validator)) { |
| IDecl = C.getCorrectionDeclAs<ObjCInterfaceDecl>(); |
| Diag(IdLoc, diag::err_undef_interface_suggest) |
| << Id << IDecl->getDeclName() |
| << FixItHint::CreateReplacement(IdLoc, IDecl->getNameAsString()); |
| Diag(IDecl->getLocation(), diag::note_previous_decl) |
| << IDecl->getDeclName(); |
| |
| Id = IDecl->getIdentifier(); |
| } |
| } |
| ObjCInterfaceDecl *Def = dyn_cast_or_null<ObjCInterfaceDecl>(IDecl); |
| // This routine must always return a class definition, if any. |
| if (Def && Def->getDefinition()) |
| Def = Def->getDefinition(); |
| return Def; |
| } |
| |
| /// getNonFieldDeclScope - Retrieves the innermost scope, starting |
| /// from S, where a non-field would be declared. This routine copes |
| /// with the difference between C and C++ scoping rules in structs and |
| /// unions. For example, the following code is well-formed in C but |
| /// ill-formed in C++: |
| /// @code |
| /// struct S6 { |
| /// enum { BAR } e; |
| /// }; |
| /// |
| /// void test_S6() { |
| /// struct S6 a; |
| /// a.e = BAR; |
| /// } |
| /// @endcode |
| /// For the declaration of BAR, this routine will return a different |
| /// scope. The scope S will be the scope of the unnamed enumeration |
| /// within S6. In C++, this routine will return the scope associated |
| /// with S6, because the enumeration's scope is a transparent |
| /// context but structures can contain non-field names. In C, this |
| /// routine will return the translation unit scope, since the |
| /// enumeration's scope is a transparent context and structures cannot |
| /// contain non-field names. |
| Scope *Sema::getNonFieldDeclScope(Scope *S) { |
| while (((S->getFlags() & Scope::DeclScope) == 0) || |
| (S->getEntity() && |
| ((DeclContext *)S->getEntity())->isTransparentContext()) || |
| (S->isClassScope() && !getLangOpts().CPlusPlus)) |
| S = S->getParent(); |
| return S; |
| } |
| |
| /// LazilyCreateBuiltin - The specified Builtin-ID was first used at |
| /// file scope. lazily create a decl for it. ForRedeclaration is true |
| /// if we're creating this built-in in anticipation of redeclaring the |
| /// built-in. |
| NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, |
| Scope *S, bool ForRedeclaration, |
| SourceLocation Loc) { |
| Builtin::ID BID = (Builtin::ID)bid; |
| |
| ASTContext::GetBuiltinTypeError Error; |
| QualType R = Context.GetBuiltinType(BID, Error); |
| switch (Error) { |
| case ASTContext::GE_None: |
| // Okay |
| break; |
| |
| case ASTContext::GE_Missing_stdio: |
| if (ForRedeclaration) |
| Diag(Loc, diag::warn_implicit_decl_requires_stdio) |
| << Context.BuiltinInfo.GetName(BID); |
| return 0; |
| |
| case ASTContext::GE_Missing_setjmp: |
| if (ForRedeclaration) |
| Diag(Loc, diag::warn_implicit_decl_requires_setjmp) |
| << Context.BuiltinInfo.GetName(BID); |
| return 0; |
| |
| case ASTContext::GE_Missing_ucontext: |
| if (ForRedeclaration) |
| Diag(Loc, diag::warn_implicit_decl_requires_ucontext) |
| << Context.BuiltinInfo.GetName(BID); |
| return 0; |
| } |
| |
| if (!ForRedeclaration && Context.BuiltinInfo.isPredefinedLibFunction(BID)) { |
| Diag(Loc, diag::ext_implicit_lib_function_decl) |
| << Context.BuiltinInfo.GetName(BID) |
| << R; |
| if (Context.BuiltinInfo.getHeaderName(BID) && |
| Diags.getDiagnosticLevel(diag::ext_implicit_lib_function_decl, Loc) |
| != DiagnosticsEngine::Ignored) |
| Diag(Loc, diag::note_please_include_header) |
| << Context.BuiltinInfo.getHeaderName(BID) |
| << Context.BuiltinInfo.GetName(BID); |
| } |
| |
| FunctionDecl *New = FunctionDecl::Create(Context, |
| Context.getTranslationUnitDecl(), |
| Loc, Loc, II, R, /*TInfo=*/0, |
| SC_Extern, |
| SC_None, false, |
| /*hasPrototype=*/true); |
| New->setImplicit(); |
| |
| // Create Decl objects for each parameter, adding them to the |
| // FunctionDecl. |
| if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(R)) { |
| SmallVector<ParmVarDecl*, 16> Params; |
| for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i) { |
| ParmVarDecl *parm = |
| ParmVarDecl::Create(Context, New, SourceLocation(), |
| SourceLocation(), 0, |
| FT->getArgType(i), /*TInfo=*/0, |
| SC_None, SC_None, 0); |
| parm->setScopeInfo(0, i); |
| Params.push_back(parm); |
| } |
| New->setParams(Params); |
| } |
| |
| AddKnownFunctionAttributes(New); |
| |
| // TUScope is the translation-unit scope to insert this function into. |
| // FIXME: This is hideous. We need to teach PushOnScopeChains to |
| // relate Scopes to DeclContexts, and probably eliminate CurContext |
| // entirely, but we're not there yet. |
| DeclContext *SavedContext = CurContext; |
| CurContext = Context.getTranslationUnitDecl(); |
| PushOnScopeChains(New, TUScope); |
| CurContext = SavedContext; |
| return New; |
| } |
| |
| bool Sema::isIncompatibleTypedef(TypeDecl *Old, TypedefNameDecl *New) { |
| QualType OldType; |
| if (TypedefNameDecl *OldTypedef = dyn_cast<TypedefNameDecl>(Old)) |
| OldType = OldTypedef->getUnderlyingType(); |
| else |
| OldType = Context.getTypeDeclType(Old); |
| QualType NewType = New->getUnderlyingType(); |
| |
| if (NewType->isVariablyModifiedType()) { |
| // Must not redefine a typedef with a variably-modified type. |
| int Kind = isa<TypeAliasDecl>(Old) ? 1 : 0; |
| Diag(New->getLocation(), diag::err_redefinition_variably_modified_typedef) |
| << Kind << NewType; |
| if (Old->getLocation().isValid()) |
| Diag(Old->getLocation(), diag::note_previous_definition); |
| New->setInvalidDecl(); |
| return true; |
| } |
| |
| if (OldType != NewType && |
| !OldType->isDependentType() && |
| !NewType->isDependentType() && |
| !Context.hasSameType(OldType, NewType)) { |
| int Kind = isa<TypeAliasDecl>(Old) ? 1 : 0; |
| Diag(New->getLocation(), diag::err_redefinition_different_typedef) |
| << Kind << NewType << OldType; |
| if (Old->getLocation().isValid()) |
| Diag(Old->getLocation(), diag::note_previous_definition); |
| New->setInvalidDecl(); |
| return true; |
| } |
| return false; |
| } |
| |
| /// MergeTypedefNameDecl - We just parsed a typedef 'New' which has the |
| /// same name and scope as a previous declaration 'Old'. Figure out |
| /// how to resolve this situation, merging decls or emitting |
| /// diagnostics as appropriate. If there was an error, set New to be invalid. |
| /// |
| void Sema::MergeTypedefNameDecl(TypedefNameDecl *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! |
| if (getLangOpts().ObjC1) { |
| const IdentifierInfo *TypeID = New->getIdentifier(); |
| switch (TypeID->getLength()) { |
| default: break; |
| case 2: |
| { |
| if (!TypeID->isStr("id")) |
| break; |
| QualType T = New->getUnderlyingType(); |
| if (!T->isPointerType()) |
| break; |
| if (!T->isVoidPointerType()) { |
| QualType PT = T->getAs<PointerType>()->getPointeeType(); |
| if (!PT->isStructureType()) |
| break; |
| } |
| Context.setObjCIdRedefinitionType(T); |
| // Install the built-in type for 'id', ignoring the current definition. |
| New->setTypeForDecl(Context.getObjCIdType().getTypePtr()); |
| return; |
| } |
| case 5: |
| if (!TypeID->isStr("Class")) |
| break; |
| Context.setObjCClassRedefinitionType(New->getUnderlyingType()); |
| // Install the built-in type for 'Class', ignoring the current definition. |
| New->setTypeForDecl(Context.getObjCClassType().getTypePtr()); |
| return; |
| case 3: |
| if (!TypeID->isStr("SEL")) |
| break; |
| Context.setObjCSelRedefinitionType(New->getUnderlyingType()); |
| // Install the built-in type for 'SEL', ignoring the current definition. |
| New->setTypeForDecl(Context.getObjCSelType().getTypePtr()); |
| return; |
| } |
| // Fall through - the typedef name was not a builtin type. |
| } |
| |
| // Verify the old decl was also a type. |
| TypeDecl *Old = OldDecls.getAsSingle<TypeDecl>(); |
| if (!Old) { |
| 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(); |
| |
| // If the typedef types are not identical, reject them in all languages and |
| // with any extensions enabled. |
| if (isIncompatibleTypedef(Old, New)) |
| return; |
| |
| // The types match. Link up the redeclaration chain if the old |
| // declaration was a typedef. |
| if (TypedefNameDecl *Typedef = dyn_cast<TypedefNameDecl>(Old)) |
| New->setPreviousDeclaration(Typedef); |
| |
| if (getLangOpts().MicrosoftExt) |
| return; |
| |
| if (getLangOpts().CPlusPlus) { |
| // C++ [dcl.typedef]p2: |
| // In a given non-class scope, a typedef specifier can be used to |
| // redefine the name of any type declared in that scope to refer |
| // to the type to which it already refers. |
| if (!isa<CXXRecordDecl>(CurContext)) |
| return; |
| |
| // C++0x [dcl.typedef]p4: |
| // In a given class scope, a typedef specifier can be used to redefine |
| // any class-name declared in that scope that is not also a typedef-name |
| // to refer to the type to which it already refers. |
| // |
| // This wording came in via DR424, which was a correction to the |
| // wording in DR56, which accidentally banned code like: |
| // |
| // struct S { |
| // typedef struct A { } A; |
| // }; |
| // |
| // in the C++03 standard. We implement the C++0x semantics, which |
| // allow the above but disallow |
| // |
| // struct S { |
| // typedef int I; |
| // typedef int I; |
| // }; |
| // |
| // since that was the intent of DR56. |
| if (!isa<TypedefNameDecl>(Old)) |
| return; |
| |
| Diag(New->getLocation(), diag::err_redefinition) |
| << New->getDeclName(); |
| Diag(Old->getLocation(), diag::note_previous_definition); |
| return New->setInvalidDecl(); |
| } |
| |
| // Modules always permit redefinition of typedefs, as does C11. |
| if (getLangOpts().Modules || getLangOpts().C11) |
| return; |
| |
| // If we have a redefinition of a typedef in C, emit a warning. This warning |
| // is normally mapped to an error, but can be controlled with |
| // -Wtypedef-redefinition. If either the original or the redefinition is |
| // in a system header, don't emit this for compatibility with GCC. |
| if (getDiagnostics().getSuppressSystemWarnings() && |
| (Context.getSourceManager().isInSystemHeader(Old->getLocation()) || |
| Context.getSourceManager().isInSystemHeader(New->getLocation()))) |
| return; |
| |
| Diag(New->getLocation(), diag::warn_redefinition_of_typedef) |
| << New->getDeclName(); |
| Diag(Old->getLocation(), diag::note_previous_definition); |
| return; |
| } |
| |
| /// DeclhasAttr - returns true if decl Declaration already has the target |
| /// attribute. |
| static bool |
| DeclHasAttr(const Decl *D, const Attr *A) { |
| // There can be multiple AvailabilityAttr in a Decl. Make sure we copy |
| // all of them. It is mergeAvailabilityAttr in SemaDeclAttr.cpp that is |
| // responsible for making sure they are consistent. |
| const AvailabilityAttr *AA = dyn_cast<AvailabilityAttr>(A); |
| if (AA) |
| return false; |
| |
| const OwnershipAttr *OA = dyn_cast<OwnershipAttr>(A); |
| const AnnotateAttr *Ann = dyn_cast<AnnotateAttr>(A); |
| for (Decl::attr_iterator i = D->attr_begin(), e = D->attr_end(); i != e; ++i) |
| if ((*i)->getKind() == A->getKind()) { |
| if (Ann) { |
| if (Ann->getAnnotation() == cast<AnnotateAttr>(*i)->getAnnotation()) |
| return true; |
| continue; |
| } |
| // FIXME: Don't hardcode this check |
| if (OA && isa<OwnershipAttr>(*i)) |
| return OA->getOwnKind() == cast<OwnershipAttr>(*i)->getOwnKind(); |
| return true; |
| } |
| |
| return false; |
| } |
| |
| bool Sema::mergeDeclAttribute(Decl *D, InheritableAttr *Attr) { |
| InheritableAttr *NewAttr = NULL; |
| if (AvailabilityAttr *AA = dyn_cast<AvailabilityAttr>(Attr)) |
| NewAttr = mergeAvailabilityAttr(D, AA->getRange(), AA->getPlatform(), |
| AA->getIntroduced(), AA->getDeprecated(), |
| AA->getObsoleted(), AA->getUnavailable(), |
| AA->getMessage()); |
| else if (VisibilityAttr *VA = dyn_cast<VisibilityAttr>(Attr)) |
| NewAttr = mergeVisibilityAttr(D, VA->getRange(), VA->getVisibility()); |
| else if (DLLImportAttr *ImportA = dyn_cast<DLLImportAttr>(Attr)) |
| NewAttr = mergeDLLImportAttr(D, ImportA->getRange()); |
| else if (DLLExportAttr *ExportA = dyn_cast<DLLExportAttr>(Attr)) |
| NewAttr = mergeDLLExportAttr(D, ExportA->getRange()); |
| else if (FormatAttr *FA = dyn_cast<FormatAttr>(Attr)) |
| NewAttr = mergeFormatAttr(D, FA->getRange(), FA->getType(), |
| FA->getFormatIdx(), FA->getFirstArg()); |
| else if (SectionAttr *SA = dyn_cast<SectionAttr>(Attr)) |
| NewAttr = mergeSectionAttr(D, SA->getRange(), SA->getName()); |
| else if (!DeclHasAttr(D, Attr)) |
| NewAttr = cast<InheritableAttr>(Attr->clone(Context)); |
| |
| if (NewAttr) { |
| NewAttr->setInherited(true); |
| D->addAttr(NewAttr); |
| return true; |
| } |
| |
| return false; |
| } |
| |
| static const Decl *getDefinition(const Decl *D) { |
| if (const TagDecl *TD = dyn_cast<TagDecl>(D)) |
| return TD->getDefinition(); |
| if (const VarDecl *VD = dyn_cast<VarDecl>(D)) |
| return VD->getDefinition(); |
| if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { |
| const FunctionDecl* Def; |
| if (FD->hasBody(Def)) |
| return Def; |
| } |
| return NULL; |
| } |
| |
| static bool hasAttribute(const Decl *D, attr::Kind Kind) { |
| for (Decl::attr_iterator I = D->attr_begin(), E = D->attr_end(); |
| I != E; ++I) { |
| Attr *Attribute = *I; |
| if (Attribute->getKind() == Kind) |
| return true; |
| } |
| return false; |
| } |
| |
| /// checkNewAttributesAfterDef - If we already have a definition, check that |
| /// there are no new attributes in this declaration. |
| static void checkNewAttributesAfterDef(Sema &S, Decl *New, const Decl *Old) { |
| if (!New->hasAttrs()) |
| return; |
| |
| const Decl *Def = getDefinition(Old); |
| if (!Def || Def == New) |
| return; |
| |
| AttrVec &NewAttributes = New->getAttrs(); |
| for (unsigned I = 0, E = NewAttributes.size(); I != E;) { |
| const Attr *NewAttribute = NewAttributes[I]; |
| if (hasAttribute(Def, NewAttribute->getKind())) { |
| ++I; |
| continue; // regular attr merging will take care of validating this. |
| } |
| S.Diag(NewAttribute->getLocation(), |
| diag::warn_attribute_precede_definition); |
| S.Diag(Def->getLocation(), diag::note_previous_definition); |
| NewAttributes.erase(NewAttributes.begin() + I); |
| --E; |
| } |
| } |
| |
| /// mergeDeclAttributes - Copy attributes from the Old decl to the New one. |
| void Sema::mergeDeclAttributes(Decl *New, Decl *Old, |
| bool MergeDeprecation) { |
| // attributes declared post-definition are currently ignored |
| checkNewAttributesAfterDef(*this, New, Old); |
| |
| if (!Old->hasAttrs()) |
| return; |
| |
| bool foundAny = New->hasAttrs(); |
| |
| // Ensure that any moving of objects within the allocated map is done before |
| // we process them. |
| if (!foundAny) New->setAttrs(AttrVec()); |
| |
| for (specific_attr_iterator<InheritableAttr> |
| i = Old->specific_attr_begin<InheritableAttr>(), |
| e = Old->specific_attr_end<InheritableAttr>(); |
| i != e; ++i) { |
| // Ignore deprecated/unavailable/availability attributes if requested. |
| if (!MergeDeprecation && |
| (isa<DeprecatedAttr>(*i) || |
| isa<UnavailableAttr>(*i) || |
| isa<AvailabilityAttr>(*i))) |
| continue; |
| |
| if (mergeDeclAttribute(New, *i)) |
| foundAny = true; |
| } |
| |
| if (!foundAny) New->dropAttrs(); |
| } |
| |
| /// mergeParamDeclAttributes - Copy attributes from the old parameter |
| /// to the new one. |
| static void mergeParamDeclAttributes(ParmVarDecl *newDecl, |
| const ParmVarDecl *oldDecl, |
| ASTContext &C) { |
| if (!oldDecl->hasAttrs()) |
| return; |
| |
| bool foundAny = newDecl->hasAttrs(); |
| |
| // Ensure that any moving of objects within the allocated map is |
| // done before we process them. |
| if (!foundAny) newDecl->setAttrs(AttrVec()); |
| |
| for (specific_attr_iterator<InheritableParamAttr> |
| i = oldDecl->specific_attr_begin<InheritableParamAttr>(), |
| e = oldDecl->specific_attr_end<InheritableParamAttr>(); i != e; ++i) { |
| if (!DeclHasAttr(newDecl, *i)) { |
| InheritableAttr *newAttr = cast<InheritableParamAttr>((*i)->clone(C)); |
| newAttr->setInherited(true); |
| newDecl->addAttr(newAttr); |
| foundAny = true; |
| } |
| } |
| |
| if (!foundAny) newDecl->dropAttrs(); |
| } |
| |
| namespace { |
| |
| /// Used in MergeFunctionDecl to keep track of function parameters in |
| /// C. |
| struct GNUCompatibleParamWarning { |
| ParmVarDecl *OldParm; |
| ParmVarDecl *NewParm; |
| QualType PromotedType; |
| }; |
| |
| } |
| |
| /// getSpecialMember - get the special member enum for a method. |
| Sema::CXXSpecialMember Sema::getSpecialMember(const CXXMethodDecl *MD) { |
| if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(MD)) { |
| if (Ctor->isDefaultConstructor()) |
| return Sema::CXXDefaultConstructor; |
| |
| if (Ctor->isCopyConstructor()) |
| return Sema::CXXCopyConstructor; |
| |
| if (Ctor->isMoveConstructor()) |
| return Sema::CXXMoveConstructor; |
| } else if (isa<CXXDestructorDecl>(MD)) { |
| return Sema::CXXDestructor; |
| } else if (MD->isCopyAssignmentOperator()) { |
| return Sema::CXXCopyAssignment; |
| } else if (MD->isMoveAssignmentOperator()) { |
| return Sema::CXXMoveAssignment; |
| } |
| |
| return Sema::CXXInvalid; |
| } |
| |
| /// canRedefineFunction - checks if a function can be redefined. Currently, |
| /// only extern inline functions can be redefined, and even then only in |
| /// GNU89 mode. |
| static bool canRedefineFunction(const FunctionDecl *FD, |
| const LangOptions& LangOpts) { |
| return ((FD->hasAttr<GNUInlineAttr>() || LangOpts.GNUInline) && |
| !LangOpts.CPlusPlus && |
| FD->isInlineSpecified() && |
| FD->getStorageClass() == SC_Extern); |
| } |
| |
| /// Is the given calling convention the ABI default for the given |
| /// declaration? |
| static bool isABIDefaultCC(Sema &S, CallingConv CC, FunctionDecl *D) { |
| CallingConv ABIDefaultCC; |
| if (isa<CXXMethodDecl>(D) && cast<CXXMethodDecl>(D)->isInstance()) { |
| ABIDefaultCC = S.Context.getDefaultCXXMethodCallConv(D->isVariadic()); |
| } else { |
| // Free C function or a static method. |
| ABIDefaultCC = (S.Context.getLangOpts().MRTD ? CC_X86StdCall : CC_C); |
| } |
| return ABIDefaultCC == CC; |
| } |
| |
| /// MergeFunctionDecl - We just parsed a function 'New' from |
| /// declarator D which has the same name and scope as a previous |
| /// declaration 'Old'. Figure out how to resolve this situation, |
| /// merging decls or emitting diagnostics as appropriate. |
| /// |
| /// In C++, New and Old must be declarations that are not |
| /// overloaded. Use IsOverload to determine whether New and Old are |
| /// overloaded, and to select the Old declaration that New should be |
| /// merged with. |
| /// |
| /// Returns true if there was an error, false otherwise. |
| bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) { |
| // Verify the old decl was also a function. |
| FunctionDecl *Old = 0; |
| if (FunctionTemplateDecl *OldFunctionTemplate |
| = dyn_cast<FunctionTemplateDecl>(OldD)) |
| Old = OldFunctionTemplate->getTemplatedDecl(); |
| else |
| Old = dyn_cast<FunctionDecl>(OldD); |
| if (!Old) { |
| if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(OldD)) { |
| Diag(New->getLocation(), diag::err_using_decl_conflict_reverse); |
| Diag(Shadow->getTargetDecl()->getLocation(), |
| diag::note_using_decl_target); |
| Diag(Shadow->getUsingDecl()->getLocation(), |
| diag::note_using_decl) << 0; |
| return true; |
| } |
| |
| Diag(New->getLocation(), diag::err_redefinition_different_kind) |
| << New->getDeclName(); |
| Diag(OldD->getLocation(), diag::note_previous_definition); |
| return true; |
| } |
| |
| // Determine whether the previous declaration was a definition, |
| // implicit declaration, or a declaration. |
| diag::kind PrevDiag; |
| if (Old->isThisDeclarationADefinition()) |
| PrevDiag = diag::note_previous_definition; |
| else if (Old->isImplicit()) |
| PrevDiag = diag::note_previous_implicit_declaration; |
| else |
| PrevDiag = diag::note_previous_declaration; |
| |
| QualType OldQType = Context.getCanonicalType(Old->getType()); |
| QualType NewQType = Context.getCanonicalType(New->getType()); |
| |
| // Don't complain about this if we're in GNU89 mode and the old function |
| // is an extern inline function. |
| if (!isa<CXXMethodDecl>(New) && !isa<CXXMethodDecl>(Old) && |
| New->getStorageClass() == SC_Static && |
| Old->getStorageClass() != SC_Static && |
| !canRedefineFunction(Old, getLangOpts())) { |
| if (getLangOpts().MicrosoftExt) { |
| Diag(New->getLocation(), diag::warn_static_non_static) << New; |
| Diag(Old->getLocation(), PrevDiag); |
| } else { |
| Diag(New->getLocation(), diag::err_static_non_static) << New; |
| Diag(Old->getLocation(), PrevDiag); |
| return true; |
| } |
| } |
| |
| // If a function is first declared with a calling convention, but is |
| // later declared or defined without one, the second decl assumes the |
| // calling convention of the first. |
| // |
| // It's OK if a function is first declared without a calling convention, |
| // but is later declared or defined with the default calling convention. |
| // |
| // For the new decl, we have to look at the NON-canonical type to tell the |
| // difference between a function that really doesn't have a calling |
| // convention and one that is declared cdecl. That's because in |
| // canonicalization (see ASTContext.cpp), cdecl is canonicalized away |
| // because it is the default calling convention. |
| // |
| // Note also that we DO NOT return at this point, because we still have |
| // other tests to run. |
| const FunctionType *OldType = cast<FunctionType>(OldQType); |
| const FunctionType *NewType = New->getType()->getAs<FunctionType>(); |
| FunctionType::ExtInfo OldTypeInfo = OldType->getExtInfo(); |
| FunctionType::ExtInfo NewTypeInfo = NewType->getExtInfo(); |
| bool RequiresAdjustment = false; |
| if (OldTypeInfo.getCC() == NewTypeInfo.getCC()) { |
| // Fast path: nothing to do. |
| |
| // Inherit the CC from the previous declaration if it was specified |
| // there but not here. |
| } else if (NewTypeInfo.getCC() == CC_Default) { |
| NewTypeInfo = NewTypeInfo.withCallingConv(OldTypeInfo.getCC()); |
| RequiresAdjustment = true; |
| |
| // Don't complain about mismatches when the default CC is |
| // effectively the same as the explict one. |
| } else if (OldTypeInfo.getCC() == CC_Default && |
| isABIDefaultCC(*this, NewTypeInfo.getCC(), New)) { |
| NewTypeInfo = NewTypeInfo.withCallingConv(OldTypeInfo.getCC()); |
| RequiresAdjustment = true; |
| |
| } else if (!Context.isSameCallConv(OldTypeInfo.getCC(), |
| NewTypeInfo.getCC())) { |
| // Calling conventions really aren't compatible, so complain. |
| Diag(New->getLocation(), diag::err_cconv_change) |
| << FunctionType::getNameForCallConv(NewTypeInfo.getCC()) |
| << (OldTypeInfo.getCC() == CC_Default) |
| << (OldTypeInfo.getCC() == CC_Default ? "" : |
| FunctionType::getNameForCallConv(OldTypeInfo.getCC())); |
| Diag(Old->getLocation(), diag::note_previous_declaration); |
| return true; |
| } |
| |
| // FIXME: diagnose the other way around? |
| if (OldTypeInfo.getNoReturn() && !NewTypeInfo.getNoReturn()) { |
| NewTypeInfo = NewTypeInfo.withNoReturn(true); |
| RequiresAdjustment = true; |
| } |
| |
| // Merge regparm attribute. |
| if (OldTypeInfo.getHasRegParm() != NewTypeInfo.getHasRegParm() || |
| OldTypeInfo.getRegParm() != NewTypeInfo.getRegParm()) { |
| if (NewTypeInfo.getHasRegParm()) { |
| Diag(New->getLocation(), diag::err_regparm_mismatch) |
| << NewType->getRegParmType() |
| << OldType->getRegParmType(); |
| Diag(Old->getLocation(), diag::note_previous_declaration); |
| return true; |
| } |
| |
| NewTypeInfo = NewTypeInfo.withRegParm(OldTypeInfo.getRegParm()); |
| RequiresAdjustment = true; |
| } |
| |
| // Merge ns_returns_retained attribute. |
| if (OldTypeInfo.getProducesResult() != NewTypeInfo.getProducesResult()) { |
| if (NewTypeInfo.getProducesResult()) { |
| Diag(New->getLocation(), diag::err_returns_retained_mismatch); |
| Diag(Old->getLocation(), diag::note_previous_declaration); |
| return true; |
| } |
| |
| NewTypeInfo = NewTypeInfo.withProducesResult(true); |
| RequiresAdjustment = true; |
| } |
| |
| if (RequiresAdjustment) { |
| NewType = Context.adjustFunctionType(NewType, NewTypeInfo); |
| New->setType(QualType(NewType, 0)); |
| NewQType = Context.getCanonicalType(New->getType()); |
| } |
| |
| if (getLangOpts().CPlusPlus) { |
| // (C++98 13.1p2): |
| // Certain function declarations cannot be overloaded: |
| // -- Function declarations that differ only in the return type |
| // cannot be overloaded. |
| QualType OldReturnType = OldType->getResultType(); |
| QualType NewReturnType = cast<FunctionType>(NewQType)->getResultType(); |
| QualType ResQT; |
| if (OldReturnType != NewReturnType) { |
| if (NewReturnType->isObjCObjectPointerType() |
| && OldReturnType->isObjCObjectPointerType()) |
| ResQT = Context.mergeObjCGCQualifiers(NewQType, OldQType); |
| if (ResQT.isNull()) { |
| if (New->isCXXClassMember() && New->isOutOfLine()) |
| Diag(New->getLocation(), |
| diag::err_member_def_does_not_match_ret_type) << New; |
| else |
| Diag(New->getLocation(), diag::err_ovl_diff_return_type); |
| Diag(Old->getLocation(), PrevDiag) << Old << Old->getType(); |
| return true; |
| } |
| else |
| NewQType = ResQT; |
| } |
| |
| const CXXMethodDecl* OldMethod = dyn_cast<CXXMethodDecl>(Old); |
| CXXMethodDecl* NewMethod = dyn_cast<CXXMethodDecl>(New); |
| if (OldMethod && NewMethod) { |
| // Preserve triviality. |
| NewMethod->setTrivial(OldMethod->isTrivial()); |
| |
| // MSVC allows explicit template specialization at class scope: |
| // 2 CXMethodDecls referring to the same function will be injected. |
| // We don't want a redeclartion error. |
| bool IsClassScopeExplicitSpecialization = |
| OldMethod->isFunctionTemplateSpecialization() && |
| NewMethod->isFunctionTemplateSpecialization(); |
| bool isFriend = NewMethod->getFriendObjectKind(); |
| |
| if (!isFriend && NewMethod->getLexicalDeclContext()->isRecord() && |
| !IsClassScopeExplicitSpecialization) { |
| // -- Member function declarations with the same name and the |
| // same parameter types cannot be overloaded if any of them |
| // is a static member function declaration. |
| if (OldMethod->isStatic() || NewMethod->isStatic()) { |
| Diag(New->getLocation(), diag::err_ovl_static_nonstatic_member); |
| Diag(Old->getLocation(), PrevDiag) << Old << Old->getType(); |
| return true; |
| } |
| |
| // C++ [class.mem]p1: |
| // [...] A member shall not be declared twice in the |
| // member-specification, except that a nested class or member |
| // class template can be declared and then later defined. |
| if (ActiveTemplateInstantiations.empty()) { |
| unsigned NewDiag; |
| if (isa<CXXConstructorDecl>(OldMethod)) |
| NewDiag = diag::err_constructor_redeclared; |
| else if (isa<CXXDestructorDecl>(NewMethod)) |
| NewDiag = diag::err_destructor_redeclared; |
| else if (isa<CXXConversionDecl>(NewMethod)) |
| NewDiag = diag::err_conv_function_redeclared; |
| else |
| NewDiag = diag::err_member_redeclared; |
| |
| Diag(New->getLocation(), NewDiag); |
| } else { |
| Diag(New->getLocation(), diag::err_member_redeclared_in_instantiation) |
| << New << New->getType(); |
| } |
| Diag(Old->getLocation(), PrevDiag) << Old << Old->getType(); |
| |
| // Complain if this is an explicit declaration of a special |
| // member that was initially declared implicitly. |
| // |
| // As an exception, it's okay to befriend such methods in order |
| // to permit the implicit constructor/destructor/operator calls. |
| } else if (OldMethod->isImplicit()) { |
| if (isFriend) { |
| NewMethod->setImplicit(); |
| } else { |
| Diag(NewMethod->getLocation(), |
| diag::err_definition_of_implicitly_declared_member) |
| << New << getSpecialMember(OldMethod); |
| return true; |
| } |
| } else if (OldMethod->isExplicitlyDefaulted() && !isFriend) { |
| Diag(NewMethod->getLocation(), |
| diag::err_definition_of_explicitly_defaulted_member) |
| << getSpecialMember(OldMethod); |
| return true; |
| } |
| } |
| |
| // (C++98 8.3.5p3): |
| // All declarations for a function shall agree exactly in both the |
| // return type and the parameter-type-list. |
| // We also want to respect all the extended bits except noreturn. |
| |
| // noreturn should now match unless the old type info didn't have it. |
| QualType OldQTypeForComparison = OldQType; |
| if (!OldTypeInfo.getNoReturn() && NewTypeInfo.getNoReturn()) { |
| assert(OldQType == QualType(OldType, 0)); |
| const FunctionType *OldTypeForComparison |
| = Context.adjustFunctionType(OldType, OldTypeInfo.withNoReturn(true)); |
| OldQTypeForComparison = QualType(OldTypeForComparison, 0); |
| assert(OldQTypeForComparison.isCanonical()); |
| } |
| |
| if (OldQTypeForComparison == NewQType) |
| return MergeCompatibleFunctionDecls(New, Old, S); |
| |
| // Fall through for conflicting redeclarations and redefinitions. |
| } |
| |
| // C: Function types need to be compatible, not identical. This handles |
| // duplicate function decls like "void f(int); void f(enum X);" properly. |
| if (!getLangOpts().CPlusPlus && |
| Context.typesAreCompatible(OldQType, NewQType)) { |
| const FunctionType *OldFuncType = OldQType->getAs<FunctionType>(); |
| const FunctionType *NewFuncType = NewQType->getAs<FunctionType>(); |
| const FunctionProtoType *OldProto = 0; |
| if (isa<FunctionNoProtoType>(NewFuncType) && |
| (OldProto = dyn_cast<FunctionProtoType>(OldFuncType))) { |
| // The old declaration provided a function prototype, but the |
| // new declaration does not. Merge in the prototype. |
| assert(!OldProto->hasExceptionSpec() && "Exception spec in C"); |
| SmallVector<QualType, 16> ParamTypes(OldProto->arg_type_begin(), |
| OldProto->arg_type_end()); |
| NewQType = Context.getFunctionType(NewFuncType->getResultType(), |
| ParamTypes.data(), ParamTypes.size(), |
| OldProto->getExtProtoInfo()); |
| New->setType(NewQType); |
| New->setHasInheritedPrototype(); |
| |
| // Synthesize a parameter for each argument type. |
| SmallVector<ParmVarDecl*, 16> Params; |
| for (FunctionProtoType::arg_type_iterator |
| ParamType = OldProto->arg_type_begin(), |
| ParamEnd = OldProto->arg_type_end(); |
| ParamType != ParamEnd; ++ParamType) { |
| ParmVarDecl *Param = ParmVarDecl::Create(Context, New, |
| SourceLocation(), |
| SourceLocation(), 0, |
| *ParamType, /*TInfo=*/0, |
| SC_None, SC_None, |
| 0); |
| Param->setScopeInfo(0, Params.size()); |
| Param->setImplicit(); |
| Params.push_back(Param); |
| } |
| |
| New->setParams(Params); |
| } |
| |
| return MergeCompatibleFunctionDecls(New, Old, S); |
| } |
| |
| // GNU C permits a K&R definition to follow a prototype declaration |
| // if the declared types of the parameters in the K&R definition |
| // match the types in the prototype declaration, even when the |
| // promoted types of the parameters from the K&R definition differ |
| // from the types in the prototype. GCC then keeps the types from |
| // the prototype. |
| // |
| // If a variadic prototype is followed by a non-variadic K&R definition, |
| // the K&R definition becomes variadic. This is sort of an edge case, but |
| // it's legal per the standard depending on how you read C99 6.7.5.3p15 and |
| // C99 6.9.1p8. |
| if (!getLangOpts().CPlusPlus && |
| Old->hasPrototype() && !New->hasPrototype() && |
| New->getType()->getAs<FunctionProtoType>() && |
| Old->getNumParams() == New->getNumParams()) { |
| SmallVector<QualType, 16> ArgTypes; |
| SmallVector<GNUCompatibleParamWarning, 16> Warnings; |
| const FunctionProtoType *OldProto |
| = Old->getType()->getAs<FunctionProtoType>(); |
| const FunctionProtoType *NewProto |
| = New->getType()->getAs<FunctionProtoType>(); |
| |
| // Determine whether this is the GNU C extension. |
| QualType MergedReturn = Context.mergeTypes(OldProto->getResultType(), |
| NewProto->getResultType()); |
| bool LooseCompatible = !MergedReturn.isNull(); |
| for (unsigned Idx = 0, End = Old->getNumParams(); |
| LooseCompatible && Idx != End; ++Idx) { |
| ParmVarDecl *OldParm = Old->getParamDecl(Idx); |
| ParmVarDecl *NewParm = New->getParamDecl(Idx); |
| if (Context.typesAreCompatible(OldParm->getType(), |
| NewProto->getArgType(Idx))) { |
| ArgTypes.push_back(NewParm->getType()); |
| } else if (Context.typesAreCompatible(OldParm->getType(), |
| NewParm->getType(), |
| /*CompareUnqualified=*/true)) { |
| GNUCompatibleParamWarning Warn |
| = { OldParm, NewParm, NewProto->getArgType(Idx) }; |
| Warnings.push_back(Warn); |
| ArgTypes.push_back(NewParm->getType()); |
| } else |
| LooseCompatible = false; |
| } |
| |
| if (LooseCompatible) { |
| for (unsigned Warn = 0; Warn < Warnings.size(); ++Warn) { |
| Diag(Warnings[Warn].NewParm->getLocation(), |
| diag::ext_param_promoted_not_compatible_with_prototype) |
| << Warnings[Warn].PromotedType |
| << Warnings[Warn].OldParm->getType(); |
| if (Warnings[Warn].OldParm->getLocation().isValid()) |
| Diag(Warnings[Warn].OldParm->getLocation(), |
| diag::note_previous_declaration); |
| } |
| |
| New->setType(Context.getFunctionType(MergedReturn, &ArgTypes[0], |
| ArgTypes.size(), |
| OldProto->getExtProtoInfo())); |
| return MergeCompatibleFunctionDecls(New, Old, S); |
| } |
| |
| // Fall through to diagnose conflicting types. |
| } |
| |
| // A function that has already been declared has been redeclared or defined |
| // with a different type- show appropriate diagnostic |
| if (unsigned BuiltinID = Old->getBuiltinID()) { |
| // The user has declared a builtin function with an incompatible |
| // signature. |
| if (Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) { |
| // The function the user is redeclaring is a library-defined |
| // function like 'malloc' or 'printf'. Warn about the |
| // redeclaration, then pretend that we don't know about this |
| // library built-in. |
| Diag(New->getLocation(), diag::warn_redecl_library_builtin) << New; |
| Diag(Old->getLocation(), diag::note_previous_builtin_declaration) |
| << Old << Old->getType(); |
| New->getIdentifier()->setBuiltinID(Builtin::NotBuiltin); |
| Old->setInvalidDecl(); |
| return false; |
| } |
| |
| PrevDiag = diag::note_previous_builtin_declaration; |
| } |
| |
| Diag(New->getLocation(), diag::err_conflicting_types) << New->getDeclName(); |
| Diag(Old->getLocation(), PrevDiag) << Old << Old->getType(); |
| return true; |
| } |
| |
| /// \brief Completes the merge of two function declarations that are |
| /// known to be compatible. |
| /// |
| /// This routine handles the merging of attributes and other |
| /// properties of function declarations form the old declaration to |
| /// the new declaration, once we know that New is in fact a |
| /// redeclaration of Old. |
| /// |
| /// \returns false |
| bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old, |
| Scope *S) { |
| // Merge the attributes |
| mergeDeclAttributes(New, Old); |
| |
| // Merge the storage class. |
| if (Old->getStorageClass() != SC_Extern && |
| Old->getStorageClass() != SC_None) |
| New->setStorageClass(Old->getStorageClass()); |
| |
| // Merge "pure" flag. |
| if (Old->isPure()) |
| New->setPure(); |
| |
| // Merge attributes from the parameters. These can mismatch with K&R |
| // declarations. |
| if (New->getNumParams() == Old->getNumParams()) |
| for (unsigned i = 0, e = New->getNumParams(); i != e; ++i) |
| mergeParamDeclAttributes(New->getParamDecl(i), Old->getParamDecl(i), |
| Context); |
| |
| if (getLangOpts().CPlusPlus) |
| return MergeCXXFunctionDecl(New, Old, S); |
| |
| return false; |
| } |
| |
| |
| void Sema::mergeObjCMethodDecls(ObjCMethodDecl *newMethod, |
| ObjCMethodDecl *oldMethod) { |
| |
| // Merge the attributes, including deprecated/unavailable |
| mergeDeclAttributes(newMethod, oldMethod, /* mergeDeprecation */true); |
| |
| // Merge attributes from the parameters. |
| ObjCMethodDecl::param_const_iterator oi = oldMethod->param_begin(), |
| oe = oldMethod->param_end(); |
| for (ObjCMethodDecl::param_iterator |
| ni = newMethod->param_begin(), ne = newMethod->param_end(); |
| ni != ne && oi != oe; ++ni, ++oi) |
| mergeParamDeclAttributes(*ni, *oi, Context); |
| |
| CheckObjCMethodOverride(newMethod, oldMethod, true); |
| } |
| |
| /// MergeVarDeclTypes - We parsed a variable 'New' which has the same name and |
| /// scope as a previous declaration 'Old'. Figure out how to merge their types, |
| /// emitting diagnostics as appropriate. |
| /// |
| /// Declarations using the auto type specifier (C++ [decl.spec.auto]) call back |
| /// to here in AddInitializerToDecl. We can't check them before the initializer |
| /// is attached. |
| void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old) { |
| if (New->isInvalidDecl() || Old->isInvalidDecl()) |
| return; |
| |
| QualType MergedT; |
| if (getLangOpts().CPlusPlus) { |
| AutoType *AT = New->getType()->getContainedAutoType(); |
| if (AT && !AT->isDeduced()) { |
| // We don't know what the new type is until the initializer is attached. |
| return; |
| } else if (Context.hasSameType(New->getType(), Old->getType())) { |
| // These could still be something that needs exception specs checked. |
| return MergeVarDeclExceptionSpecs(New, Old); |
| } |
| // C++ [basic.link]p10: |
| // [...] the types specified by all declarations referring to a given |
| // object or function shall be identical, except that declarations for an |
| // array object can specify array types that differ by the presence or |
| // absence of a major array bound (8.3.4). |
| else if (Old->getType()->isIncompleteArrayType() && |
| New->getType()->isArrayType()) { |
| CanQual<ArrayType> OldArray |
| = Context.getCanonicalType(Old->getType())->getAs<ArrayType>(); |
| CanQual<ArrayType> NewArray |
| = Context.getCanonicalType(New->getType())->getAs<ArrayType>(); |
| if (OldArray->getElementType() == NewArray->getElementType()) |
| MergedT = New->getType(); |
| } else if (Old->getType()->isArrayType() && |
| New->getType()->isIncompleteArrayType()) { |
| CanQual<ArrayType> OldArray |
| = Context.getCanonicalType(Old->getType())->getAs<ArrayType>(); |
| CanQual<ArrayType> NewArray |
| = Context.getCanonicalType(New->getType())->getAs<ArrayType>(); |
| if (OldArray->getElementType() == NewArray->getElementType()) |
| MergedT = Old->getType(); |
| } else if (New->getType()->isObjCObjectPointerType() |
| && Old->getType()->isObjCObjectPointerType()) { |
| MergedT = Context.mergeObjCGCQualifiers(New->getType(), |
| Old->getType()); |
| } |
| } else { |
| MergedT = Context.mergeTypes(New->getType(), Old->getType()); |
| } |
| if (MergedT.isNull()) { |
| Diag(New->getLocation(), diag::err_redefinition_different_type) |
| << New->getDeclName(); |
| Diag(Old->getLocation(), diag::note_previous_definition); |
| return New->setInvalidDecl(); |
| } |
| New->setType(MergedT); |
| } |
| |
| /// MergeVarDecl - We just parsed a variable 'New' which has the same name |
| /// and scope as a previous declaration 'Old'. Figure out how to resolve this |
| /// situation, merging decls or emitting diagnostics as appropriate. |
| /// |
| /// Tentative definition rules (C99 6.9.2p2) are checked by |
| /// FinalizeDeclaratorGroup. Unfortunately, we can't analyze tentative |
| /// definitions here, since the initializer hasn't been attached. |
| /// |
| 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 = 0; |
| if (!Previous.isSingleResult() || |
| !(Old = dyn_cast<VarDecl>(Previous.getFoundDecl()))) { |
| Diag(New->getLocation(), diag::err_redefinition_different_kind) |
| << New->getDeclName(); |
| Diag(Previous.getRepresentativeDecl()->getLocation(), |
| diag::note_previous_definition); |
| return New->setInvalidDecl(); |
| } |
| |
| // C++ [class.mem]p1: |
| // A member shall not be declared twice in the member-specification [...] |
| // |
| // Here, we need only consider static data members. |
| if (Old->isStaticDataMember() && !New->isOutOfLine()) { |
| Diag(New->getLocation(), diag::err_duplicate_member) |
| << New->getIdentifier(); |
| Diag(Old->getLocation(), diag::note_previous_declaration); |
| New->setInvalidDecl(); |
| } |
| |
| mergeDeclAttributes(New, Old); |
| // Warn if an already-declared variable is made a weak_import in a subsequent |
| // declaration |
| if (New->getAttr<WeakImportAttr>() && |
| Old->getStorageClass() == SC_None && |
| !Old->getAttr<WeakImportAttr>()) { |
|