diff options
Diffstat (limited to 'lib/AST')
-rw-r--r-- | lib/AST/Comment.cpp | 20 | ||||
-rw-r--r-- | lib/AST/CommentSema.cpp | 34 | ||||
-rw-r--r-- | lib/AST/Decl.cpp | 55 | ||||
-rw-r--r-- | lib/AST/DeclCXX.cpp | 13 | ||||
-rw-r--r-- | lib/AST/DeclObjC.cpp | 11 |
5 files changed, 99 insertions, 34 deletions
diff --git a/lib/AST/Comment.cpp b/lib/AST/Comment.cpp index 7a7d3dd8304e..dfa2a1665d40 100644 --- a/lib/AST/Comment.cpp +++ b/lib/AST/Comment.cpp @@ -116,6 +116,9 @@ bool ParagraphComment::isWhitespaceNoCache() const { static TypeLoc lookThroughTypedefOrTypeAliasLocs(TypeLoc &SrcTL) { TypeLoc TL = SrcTL.IgnoreParens(); + // Look through attribute types. + if (AttributedTypeLoc AttributeTL = TL.getAs<AttributedTypeLoc>()) + return AttributeTL.getModifiedLoc(); // Look through qualified types. if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>()) return QualifiedTL.getUnqualifiedLoc(); @@ -280,8 +283,25 @@ void DeclInfo::fill() { case Decl::EnumConstant: case Decl::ObjCIvar: case Decl::ObjCAtDefsField: + case Decl::ObjCProperty: { + const TypeSourceInfo *TSI; + if (const auto *VD = dyn_cast<DeclaratorDecl>(CommentDecl)) + TSI = VD->getTypeSourceInfo(); + else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(CommentDecl)) + TSI = PD->getTypeSourceInfo(); + else + TSI = nullptr; + if (TSI) { + TypeLoc TL = TSI->getTypeLoc().getUnqualifiedLoc(); + FunctionTypeLoc FTL; + if (getFunctionTypeLoc(TL, FTL)) { + ParamVars = FTL.getParams(); + ReturnType = FTL.getReturnLoc().getType(); + } + } Kind = VariableKind; break; + } case Decl::Namespace: Kind = NamespaceKind; break; diff --git a/lib/AST/CommentSema.cpp b/lib/AST/CommentSema.cpp index d39a9b26b2a8..403454d3ab7e 100644 --- a/lib/AST/CommentSema.cpp +++ b/lib/AST/CommentSema.cpp @@ -86,7 +86,7 @@ ParamCommandComment *Sema::actOnParamCommandStart( new (Allocator) ParamCommandComment(LocBegin, LocEnd, CommandID, CommandMarker); - if (!isFunctionDecl()) + if (!isFunctionDecl() && !isFunctionOrBlockPointerVarLikeDecl()) Diag(Command->getLocation(), diag::warn_doc_param_not_attached_to_a_function_decl) << CommandMarker @@ -584,7 +584,11 @@ void Sema::checkReturnsCommand(const BlockCommandComment *Command) { assert(ThisDeclInfo && "should not call this check on a bare comment"); - if (isFunctionDecl()) { + // We allow the return command for all @properties because it can be used + // to document the value that the property getter returns. + if (isObjCPropertyDecl()) + return; + if (isFunctionDecl() || isFunctionOrBlockPointerVarLikeDecl()) { if (ThisDeclInfo->ReturnType->isVoidType()) { unsigned DiagKind; switch (ThisDeclInfo->CommentDecl->getKind()) { @@ -610,8 +614,6 @@ void Sema::checkReturnsCommand(const BlockCommandComment *Command) { } return; } - else if (isObjCPropertyDecl()) - return; Diag(Command->getLocation(), diag::warn_doc_returns_not_attached_to_a_function_decl) @@ -844,6 +846,30 @@ bool Sema::isFunctionPointerVarDecl() { return false; } +bool Sema::isFunctionOrBlockPointerVarLikeDecl() { + if (!ThisDeclInfo) + return false; + if (!ThisDeclInfo->IsFilled) + inspectThisDecl(); + if (ThisDeclInfo->getKind() != DeclInfo::VariableKind || + !ThisDeclInfo->CurrentDecl) + return false; + QualType QT; + if (const auto *VD = dyn_cast<DeclaratorDecl>(ThisDeclInfo->CurrentDecl)) + QT = VD->getType(); + else if (const auto *PD = + dyn_cast<ObjCPropertyDecl>(ThisDeclInfo->CurrentDecl)) + QT = PD->getType(); + else + return false; + // We would like to warn about the 'returns'/'param' commands for + // variables that don't directly specify the function type, so type aliases + // can be ignored. + if (QT->getAs<TypedefType>()) + return false; + return QT->isFunctionPointerType() || QT->isBlockPointerType(); +} + bool Sema::isObjCPropertyDecl() { if (!ThisDeclInfo) return false; diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 094e8dcff088..0f2558e24ba5 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -2251,6 +2251,14 @@ bool VarDecl::checkInitIsICE() const { return Eval->IsICE; } +template<typename DeclT> +static DeclT *getDefinitionOrSelf(DeclT *D) { + assert(D); + if (auto *Def = D->getDefinition()) + return Def; + return D; +} + VarDecl *VarDecl::getTemplateInstantiationPattern() const { // If it's a variable template specialization, find the template or partial // specialization from which it was instantiated. @@ -2262,7 +2270,7 @@ VarDecl *VarDecl::getTemplateInstantiationPattern() const { break; VTD = NewVTD; } - return VTD->getTemplatedDecl()->getDefinition(); + return getDefinitionOrSelf(VTD->getTemplatedDecl()); } if (auto *VTPSD = From.dyn_cast<VarTemplatePartialSpecializationDecl *>()) { @@ -2271,7 +2279,7 @@ VarDecl *VarDecl::getTemplateInstantiationPattern() const { break; VTPSD = NewVTPSD; } - return VTPSD->getDefinition(); + return getDefinitionOrSelf<VarDecl>(VTPSD); } } @@ -2280,23 +2288,18 @@ VarDecl *VarDecl::getTemplateInstantiationPattern() const { VarDecl *VD = getInstantiatedFromStaticDataMember(); while (auto *NewVD = VD->getInstantiatedFromStaticDataMember()) VD = NewVD; - return VD->getDefinition(); + return getDefinitionOrSelf(VD); } } if (VarTemplateDecl *VarTemplate = getDescribedVarTemplate()) { - while (VarTemplate->getInstantiatedFromMemberTemplate()) { if (VarTemplate->isMemberSpecialization()) break; VarTemplate = VarTemplate->getInstantiatedFromMemberTemplate(); } - assert((!VarTemplate->getTemplatedDecl() || - !isTemplateInstantiation(getTemplateSpecializationKind())) && - "couldn't find pattern for variable instantiation"); - - return VarTemplate->getTemplatedDecl(); + return getDefinitionOrSelf(VarTemplate->getTemplatedDecl()); } return nullptr; } @@ -3198,9 +3201,12 @@ bool FunctionDecl::isTemplateInstantiation() const { FunctionDecl *FunctionDecl::getTemplateInstantiationPattern() const { // Handle class scope explicit specialization special case. - if (getTemplateSpecializationKind() == TSK_ExplicitSpecialization) - return getClassScopeSpecializationPattern(); - + if (getTemplateSpecializationKind() == TSK_ExplicitSpecialization) { + if (auto *Spec = getClassScopeSpecializationPattern()) + return getDefinitionOrSelf(Spec); + return nullptr; + } + // If this is a generic lambda call operator specialization, its // instantiation pattern is always its primary template's pattern // even if its primary template was instantiated from another @@ -3212,16 +3218,10 @@ FunctionDecl *FunctionDecl::getTemplateInstantiationPattern() const { if (isGenericLambdaCallOperatorSpecialization( dyn_cast<CXXMethodDecl>(this))) { - assert(getPrimaryTemplate() && "A generic lambda specialization must be " - "generated from a primary call operator " - "template"); - assert(getPrimaryTemplate()->getTemplatedDecl()->getBody() && - "A generic lambda call operator template must always have a body - " - "even if instantiated from a prototype (i.e. as written) member " - "template"); - return getPrimaryTemplate()->getTemplatedDecl(); + assert(getPrimaryTemplate() && "not a generic lambda call operator?"); + return getDefinitionOrSelf(getPrimaryTemplate()->getTemplatedDecl()); } - + if (FunctionTemplateDecl *Primary = getPrimaryTemplate()) { while (Primary->getInstantiatedFromMemberTemplate()) { // If we have hit a point where the user provided a specialization of @@ -3230,11 +3230,14 @@ FunctionDecl *FunctionDecl::getTemplateInstantiationPattern() const { break; Primary = Primary->getInstantiatedFromMemberTemplate(); } - - return Primary->getTemplatedDecl(); + + return getDefinitionOrSelf(Primary->getTemplatedDecl()); } - - return getInstantiatedFromMemberFunction(); + + if (auto *MFD = getInstantiatedFromMemberFunction()) + return getDefinitionOrSelf(MFD); + + return nullptr; } FunctionTemplateDecl *FunctionDecl::getPrimaryTemplate() const { @@ -3778,7 +3781,7 @@ EnumDecl *EnumDecl::getTemplateInstantiationPattern() const { EnumDecl *ED = getInstantiatedFromMemberEnum(); while (auto *NewED = ED->getInstantiatedFromMemberEnum()) ED = NewED; - return ED; + return getDefinitionOrSelf(ED); } } diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 2e5cec9c108f..dd8f768c5711 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -1364,6 +1364,13 @@ CXXRecordDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK) { } const CXXRecordDecl *CXXRecordDecl::getTemplateInstantiationPattern() const { + auto GetDefinitionOrSelf = + [](const CXXRecordDecl *D) -> const CXXRecordDecl * { + if (auto *Def = D->getDefinition()) + return Def; + return D; + }; + // If it's a class template specialization, find the template or partial // specialization from which it was instantiated. if (auto *TD = dyn_cast<ClassTemplateSpecializationDecl>(this)) { @@ -1374,7 +1381,7 @@ const CXXRecordDecl *CXXRecordDecl::getTemplateInstantiationPattern() const { break; CTD = NewCTD; } - return CTD->getTemplatedDecl()->getDefinition(); + return GetDefinitionOrSelf(CTD->getTemplatedDecl()); } if (auto *CTPSD = From.dyn_cast<ClassTemplatePartialSpecializationDecl *>()) { @@ -1383,7 +1390,7 @@ const CXXRecordDecl *CXXRecordDecl::getTemplateInstantiationPattern() const { break; CTPSD = NewCTPSD; } - return CTPSD->getDefinition(); + return GetDefinitionOrSelf(CTPSD); } } @@ -1392,7 +1399,7 @@ const CXXRecordDecl *CXXRecordDecl::getTemplateInstantiationPattern() const { const CXXRecordDecl *RD = this; while (auto *NewRD = RD->getInstantiatedFromMemberClass()) RD = NewRD; - return RD->getDefinition(); + return GetDefinitionOrSelf(RD); } } diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index 9218eb537a60..a12a38033c4a 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -539,9 +539,18 @@ void ObjCInterfaceDecl::getDesignatedInitializers( bool ObjCInterfaceDecl::isDesignatedInitializer(Selector Sel, const ObjCMethodDecl **InitMethod) const { + bool HasCompleteDef = isThisDeclarationADefinition(); + // During deserialization the data record for the ObjCInterfaceDecl could + // be made invariant by reusing the canonical decl. Take this into account + // when checking for the complete definition. + if (!HasCompleteDef && getCanonicalDecl()->hasDefinition() && + getCanonicalDecl()->getDefinition() == getDefinition()) + HasCompleteDef = true; + // Check for a complete definition and recover if not so. - if (!isThisDeclarationADefinition()) + if (!HasCompleteDef) return false; + if (data().ExternallyCompleted) LoadExternalDefinition(); |