aaronpuchert updated this revision to Diff 404693.
aaronpuchert added a comment.

Rename `checkDecl` to `hasDeclThat`, which should hopefully address most issues.

We leave `isFunctionPointerVarDecl` inlined for now, since it's probably wrong 
anyway. (I think we should look for fields.)


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D113795/new/

https://reviews.llvm.org/D113795

Files:
  clang/include/clang/AST/CommentSema.h
  clang/lib/AST/CommentSema.cpp

Index: clang/lib/AST/CommentSema.cpp
===================================================================
--- clang/lib/AST/CommentSema.cpp
+++ clang/lib/AST/CommentSema.cpp
@@ -86,6 +86,12 @@
   }
 }
 
+/// \returns \c true if the declaration that this comment is attached to
+/// is a pointer to function/method/block type or has such a type.
+static bool involvesFunctionType(const DeclInfo &Info) {
+  return Info.involvesFunctionType();
+}
+
 ParamCommandComment *Sema::actOnParamCommandStart(
                                       SourceLocation LocBegin,
                                       SourceLocation LocEnd,
@@ -95,7 +101,7 @@
       new (Allocator) ParamCommandComment(LocBegin, LocEnd, CommandID,
                                           CommandMarker);
 
-  if (!involvesFunctionType())
+  if (!hasDeclThat(involvesFunctionType))
     Diag(Command->getLocation(),
          diag::warn_doc_param_not_attached_to_a_function_decl)
       << CommandMarker
@@ -105,23 +111,30 @@
 }
 
 void Sema::checkFunctionDeclVerbatimLine(const BlockCommandComment *Comment) {
+  if (ThisDeclInfo)
+    inspectThisDecl();
   unsigned DiagSelect;
   switch (Comment->getCommandID()) {
   case CommandTraits::KCI_function:
   case CommandTraits::KCI_functiongroup:
-    if (isAnyFunctionDecl() || isFunctionTemplateDecl())
+    if (ThisDeclInfo && ThisDeclInfo->getKind() == DeclInfo::FunctionKind &&
+        (isa<FunctionDecl>(ThisDeclInfo->CurrentDecl) ||
+         isa<FunctionTemplateDecl>(ThisDeclInfo->CurrentDecl)))
       return;
     DiagSelect = 0;
     break;
   case CommandTraits::KCI_method:
   case CommandTraits::KCI_methodgroup:
-    if (isObjCMethodDecl())
+    if (ThisDeclInfo && ThisDeclInfo->getKind() == DeclInfo::FunctionKind &&
+        isa<ObjCMethodDecl>(ThisDeclInfo->CurrentDecl))
       return;
     DiagSelect = 1;
     break;
   case CommandTraits::KCI_callback:
-    if (isFunctionPointerVarDecl())
-      return;
+    if (ThisDeclInfo && ThisDeclInfo->getKind() == DeclInfo::VariableKind)
+      if (const auto *VD = dyn_cast<VarDecl>(ThisDeclInfo->CurrentDecl))
+        if (VD->getType()->isFunctionPointerType())
+          return;
     DiagSelect = 2;
     break;
   default:
@@ -133,35 +146,80 @@
       << Comment->getSourceRange();
 }
 
+static bool isClassOrStructDeclImpl(const Decl *D) {
+  if (auto *record = dyn_cast_or_null<RecordDecl>(D))
+    return !record->isUnion();
+
+  return false;
+}
+
+/// \return \c true if the declaration that this comment is attached to
+/// declares either struct, class or tag typedef.
+static bool isClassOrStructOrTagTypedefDecl(const DeclInfo &Info) {
+  if (!Info.CurrentDecl)
+    return false;
+
+  if (isClassOrStructDeclImpl(Info.CurrentDecl))
+    return true;
+
+  if (auto *ThisTypedefDecl = dyn_cast<TypedefDecl>(Info.CurrentDecl)) {
+    auto UnderlyingType = ThisTypedefDecl->getUnderlyingType();
+    if (auto ThisElaboratedType = dyn_cast<ElaboratedType>(UnderlyingType)) {
+      auto DesugaredType = ThisElaboratedType->desugar();
+      if (auto *DesugaredTypePtr = DesugaredType.getTypePtrOrNull()) {
+        if (auto *ThisRecordType = dyn_cast<RecordType>(DesugaredTypePtr)) {
+          return isClassOrStructDeclImpl(ThisRecordType->getAsRecordDecl());
+        }
+      }
+    }
+  }
+
+  return false;
+}
+
+static bool isObjCInterfaceDecl(const DeclInfo &Info) {
+  return isa_and_nonnull<ObjCInterfaceDecl>(Info.CurrentDecl);
+}
+
+static bool isObjCProtocolDecl(const DeclInfo &Info) {
+  return isa_and_nonnull<ObjCProtocolDecl>(Info.CurrentDecl);
+}
+
 void Sema::checkContainerDeclVerbatimLine(const BlockCommandComment *Comment) {
-  switch (Comment->getCommandID()) {
+  if (ThisDeclInfo) {
+    inspectThisDecl();
+    switch (Comment->getCommandID()) {
     case CommandTraits::KCI_class:
-      if (isClassOrStructOrTagTypedefDecl() || isClassTemplateDecl())
+      if (isClassOrStructOrTagTypedefDecl(*ThisDeclInfo) ||
+          isa_and_nonnull<ClassTemplateDecl>(ThisDeclInfo->CurrentDecl))
         return;
       // Allow @class command on @interface declarations.
       // FIXME. Currently, \class and @class are indistinguishable. So,
       // \class is also allowed on an @interface declaration
-      if (Comment->getCommandMarker() && isObjCInterfaceDecl())
+      if (Comment->getCommandMarker() && isObjCInterfaceDecl(*ThisDeclInfo))
         return;
       break;
     case CommandTraits::KCI_interface:
-      if (isObjCInterfaceDecl())
+      if (isObjCInterfaceDecl(*ThisDeclInfo))
         return;
       break;
     case CommandTraits::KCI_protocol:
-      if (isObjCProtocolDecl())
+      if (isObjCProtocolDecl(*ThisDeclInfo))
         return;
       break;
     case CommandTraits::KCI_struct:
-      if (isClassOrStructOrTagTypedefDecl())
+      if (isClassOrStructOrTagTypedefDecl(*ThisDeclInfo))
         return;
       break;
     case CommandTraits::KCI_union:
-      if (isUnionDecl())
-        return;
+      if (const RecordDecl *RD =
+              dyn_cast_or_null<RecordDecl>(ThisDeclInfo->CurrentDecl))
+        if (RD->isUnion())
+          return;
       break;
     default:
       llvm_unreachable("Unhandled command with IsRecordLikeDeclarationCommand");
+    }
   }
   Diag(Comment->getLocation(), diag::warn_doc_api_container_decl_mismatch)
       << Comment->getCommandMarker()
@@ -169,8 +227,13 @@
       << Comment->getSourceRange();
 }
 
+static bool isRecordLikeDecl(const DeclInfo &Info) {
+  return isa_and_nonnull<RecordDecl>(Info.CurrentDecl) ||
+         isObjCInterfaceDecl(Info) || isObjCProtocolDecl(Info);
+}
+
 void Sema::checkContainerDecl(const BlockCommandComment *Comment) {
-  if (isRecordLikeDecl())
+  if (hasDeclThat(isRecordLikeDecl))
     return;
   Diag(Comment->getLocation(), diag::warn_doc_container_decl_mismatch)
       << Comment->getCommandMarker()
@@ -241,6 +304,10 @@
   checkBlockCommandEmptyParagraph(Command);
 }
 
+static bool isTemplateOrSpecialization(const DeclInfo &Info) {
+  return Info.getTemplateKind() != DeclInfo::NotTemplate;
+}
+
 TParamCommandComment *Sema::actOnTParamCommandStart(
                                       SourceLocation LocBegin,
                                       SourceLocation LocEnd,
@@ -250,7 +317,7 @@
       new (Allocator) TParamCommandComment(LocBegin, LocEnd, CommandID,
                                            CommandMarker);
 
-  if (!isTemplateOrSpecialization())
+  if (!hasDeclThat(isTemplateOrSpecialization))
     Diag(Command->getLocation(),
          diag::warn_doc_tparam_not_attached_to_a_template_decl)
       << CommandMarker
@@ -272,7 +339,7 @@
                                          Arg);
   Command->setArgs(llvm::makeArrayRef(A, 1));
 
-  if (!isTemplateOrSpecialization()) {
+  if (!hasDeclThat(isTemplateOrSpecialization)) {
     // We already warned that this \\tparam is not attached to a template decl.
     return;
   }
@@ -546,12 +613,13 @@
 
 void Sema::checkReturnsCommand(const BlockCommandComment *Command) {
   assert(ThisDeclInfo && "should not call this check on a bare comment");
+  inspectThisDecl();
 
   // We allow the return command for all @properties because it can be used
   // to document the value that the property getter returns.
-  if (isObjCPropertyDecl())
+  if (ThisDeclInfo->CurrentDecl->getKind() == Decl::ObjCProperty)
     return;
-  if (involvesFunctionType()) {
+  if (involvesFunctionType(*ThisDeclInfo)) {
     assert(!ThisDeclInfo->ReturnType.isNull() &&
            "should have a valid return type");
     if (ThisDeclInfo->ReturnType->isVoidType()) {
@@ -679,7 +747,7 @@
 }
 
 void Sema::resolveParamCommandIndexes(const FullComment *FC) {
-  if (!involvesFunctionType()) {
+  if (!hasDeclThat(involvesFunctionType)) {
     // We already warned that \\param commands are not attached to a function
     // decl.
     return;
@@ -767,179 +835,21 @@
   }
 }
 
-bool Sema::involvesFunctionType() {
-  if (!ThisDeclInfo)
-    return false;
-  if (!ThisDeclInfo->IsFilled)
-    inspectThisDecl();
-  return ThisDeclInfo->involvesFunctionType();
-}
-
-bool Sema::isFunctionDecl() {
-  if (!ThisDeclInfo)
-    return false;
-  if (!ThisDeclInfo->IsFilled)
-    inspectThisDecl();
-  return ThisDeclInfo->getKind() == DeclInfo::FunctionKind;
-}
-
-bool Sema::isAnyFunctionDecl() {
-  return isFunctionDecl() && ThisDeclInfo->CurrentDecl &&
-         isa<FunctionDecl>(ThisDeclInfo->CurrentDecl);
-}
-
-bool Sema::isFunctionOrMethodVariadic() {
-  if (!ThisDeclInfo)
-    return false;
-  if (!ThisDeclInfo->IsFilled)
-    inspectThisDecl();
-  return ThisDeclInfo->IsVariadic;
-}
-
-bool Sema::isObjCMethodDecl() {
-  return isFunctionDecl() && ThisDeclInfo->CurrentDecl &&
-         isa<ObjCMethodDecl>(ThisDeclInfo->CurrentDecl);
-}
-
-bool Sema::isFunctionPointerVarDecl() {
-  if (!ThisDeclInfo)
-    return false;
-  if (!ThisDeclInfo->IsFilled)
-    inspectThisDecl();
-  if (ThisDeclInfo->getKind() == DeclInfo::VariableKind) {
-    if (const VarDecl *VD = dyn_cast_or_null<VarDecl>(ThisDeclInfo->CurrentDecl)) {
-      QualType QT = VD->getType();
-      return QT->isFunctionPointerType();
-    }
-  }
-  return false;
-}
-
-bool Sema::isObjCPropertyDecl() {
+bool Sema::hasDeclThat(bool (*check)(const DeclInfo &)) {
   if (!ThisDeclInfo)
     return false;
-  if (!ThisDeclInfo->IsFilled)
-    inspectThisDecl();
-  return ThisDeclInfo->CurrentDecl->getKind() == Decl::ObjCProperty;
-}
-
-bool Sema::isTemplateOrSpecialization() {
-  if (!ThisDeclInfo)
-    return false;
-  if (!ThisDeclInfo->IsFilled)
-    inspectThisDecl();
-  return ThisDeclInfo->getTemplateKind() != DeclInfo::NotTemplate;
-}
-
-bool Sema::isRecordLikeDecl() {
-  if (!ThisDeclInfo)
-    return false;
-  if (!ThisDeclInfo->IsFilled)
-    inspectThisDecl();
-  return isUnionDecl() || isClassOrStructDecl() || isObjCInterfaceDecl() ||
-         isObjCProtocolDecl();
-}
-
-bool Sema::isUnionDecl() {
-  if (!ThisDeclInfo)
-    return false;
-  if (!ThisDeclInfo->IsFilled)
-    inspectThisDecl();
-  if (const RecordDecl *RD =
-        dyn_cast_or_null<RecordDecl>(ThisDeclInfo->CurrentDecl))
-    return RD->isUnion();
-  return false;
-}
-static bool isClassOrStructDeclImpl(const Decl *D) {
-  if (auto *record = dyn_cast_or_null<RecordDecl>(D))
-    return !record->isUnion();
-
-  return false;
-}
-
-bool Sema::isClassOrStructDecl() {
-  if (!ThisDeclInfo)
-    return false;
-  if (!ThisDeclInfo->IsFilled)
-    inspectThisDecl();
-
-  if (!ThisDeclInfo->CurrentDecl)
-    return false;
-
-  return isClassOrStructDeclImpl(ThisDeclInfo->CurrentDecl);
-}
-
-bool Sema::isClassOrStructOrTagTypedefDecl() {
-  if (!ThisDeclInfo)
-    return false;
-  if (!ThisDeclInfo->IsFilled)
-    inspectThisDecl();
-
-  if (!ThisDeclInfo->CurrentDecl)
-    return false;
-
-  if (isClassOrStructDeclImpl(ThisDeclInfo->CurrentDecl))
-    return true;
-
-  if (auto *ThisTypedefDecl = dyn_cast<TypedefDecl>(ThisDeclInfo->CurrentDecl)) {
-    auto UnderlyingType = ThisTypedefDecl->getUnderlyingType();
-    if (auto ThisElaboratedType = dyn_cast<ElaboratedType>(UnderlyingType)) {
-      auto DesugaredType = ThisElaboratedType->desugar();
-      if (auto *DesugaredTypePtr = DesugaredType.getTypePtrOrNull()) {
-        if (auto *ThisRecordType = dyn_cast<RecordType>(DesugaredTypePtr)) {
-          return isClassOrStructDeclImpl(ThisRecordType->getAsRecordDecl());
-        }
-      }
-    }
-  }
-
-  return false;
-}
-
-bool Sema::isClassTemplateDecl() {
-  if (!ThisDeclInfo)
-    return false;
-  if (!ThisDeclInfo->IsFilled)
-    inspectThisDecl();
-  return ThisDeclInfo->CurrentDecl &&
-          (isa<ClassTemplateDecl>(ThisDeclInfo->CurrentDecl));
-}
-
-bool Sema::isFunctionTemplateDecl() {
-  if (!ThisDeclInfo)
-    return false;
-  if (!ThisDeclInfo->IsFilled)
-    inspectThisDecl();
-  return ThisDeclInfo->CurrentDecl &&
-         (isa<FunctionTemplateDecl>(ThisDeclInfo->CurrentDecl));
-}
-
-bool Sema::isObjCInterfaceDecl() {
-  if (!ThisDeclInfo)
-    return false;
-  if (!ThisDeclInfo->IsFilled)
-    inspectThisDecl();
-  return ThisDeclInfo->CurrentDecl &&
-         isa<ObjCInterfaceDecl>(ThisDeclInfo->CurrentDecl);
-}
-
-bool Sema::isObjCProtocolDecl() {
-  if (!ThisDeclInfo)
-    return false;
-  if (!ThisDeclInfo->IsFilled)
-    inspectThisDecl();
-  return ThisDeclInfo->CurrentDecl &&
-         isa<ObjCProtocolDecl>(ThisDeclInfo->CurrentDecl);
+  inspectThisDecl();
+  return check(*ThisDeclInfo);
 }
 
 ArrayRef<const ParmVarDecl *> Sema::getParamVars() {
-  if (!ThisDeclInfo->IsFilled)
-    inspectThisDecl();
+  inspectThisDecl();
   return ThisDeclInfo->ParamVars;
 }
 
 void Sema::inspectThisDecl() {
-  ThisDeclInfo->fill();
+  if (!ThisDeclInfo->IsFilled)
+    ThisDeclInfo->fill();
 }
 
 unsigned Sema::resolveParmVarReference(StringRef Name,
@@ -949,7 +859,7 @@
     if (II && II->getName() == Name)
       return i;
   }
-  if (Name == "..." && isFunctionOrMethodVariadic())
+  if (Name == "..." && ThisDeclInfo->IsVariadic)
     return ParamCommandComment::VarArgParamIndex;
   return ParamCommandComment::InvalidParamIndex;
 }
Index: clang/include/clang/AST/CommentSema.h
===================================================================
--- clang/include/clang/AST/CommentSema.h
+++ clang/include/clang/AST/CommentSema.h
@@ -204,30 +204,7 @@
   /// Emit diagnostics about unknown parametrs.
   void resolveParamCommandIndexes(const FullComment *FC);
 
-  /// \returns \c true if the declaration that this comment is attached to
-  /// is a pointer to function/method/block type or has such a type.
-  bool involvesFunctionType();
-
-  bool isFunctionDecl();
-  bool isAnyFunctionDecl();
-
-  /// \returns \c true if declaration that this comment is attached to declares
-  /// a function pointer.
-  bool isFunctionPointerVarDecl();
-  bool isFunctionOrMethodVariadic();
-  bool isObjCMethodDecl();
-  bool isObjCPropertyDecl();
-  bool isTemplateOrSpecialization();
-  bool isRecordLikeDecl();
-  bool isClassOrStructDecl();
-  /// \return \c true if the declaration that this comment is attached to
-  /// declares either struct, class or tag typedef.
-  bool isClassOrStructOrTagTypedefDecl();
-  bool isUnionDecl();
-  bool isObjCInterfaceDecl();
-  bool isObjCProtocolDecl();
-  bool isClassTemplateDecl();
-  bool isFunctionTemplateDecl();
+  bool hasDeclThat(bool (*check)(const DeclInfo &));
 
   ArrayRef<const ParmVarDecl *> getParamVars();
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to