[libc-commits] [libc] Diagnose problematic uses of constructor/destructor attribute (PR #67673)

Nick Desaulniers via libc-commits libc-commits at lists.llvm.org
Fri Oct 6 13:07:23 PDT 2023


================
@@ -2352,26 +2352,126 @@ static void handleUnusedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
   D->addAttr(::new (S.Context) UnusedAttr(S.Context, AL));
 }
 
-static void handleConstructorAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
-  uint32_t priority = ConstructorAttr::DefaultPriority;
+static void diagnoseInvalidPriority(Sema &S, uint32_t Priority,
+                                    const ParsedAttr &A,
+                                    SourceLocation PriorityLoc) {
+  constexpr uint32_t ReservedPriorityLower = 101, ReservedPriorityUpper = 65535;
+
+  // Only perform the priority check if the attribute is outside of a system
+  // header. Values <= 100 are reserved for the implementation, and libc++
+  // benefits from being able to specify values in that range. Values > 65535
+  // are reserved for historical reasons.
+  if ((Priority < ReservedPriorityLower || Priority > ReservedPriorityUpper) &&
+      !S.getSourceManager().isInSystemHeader(A.getLoc())) {
+    S.Diag(A.getLoc(), diag::warn_priority_out_of_range)
+        << PriorityLoc << A << ReservedPriorityLower << ReservedPriorityUpper;
+  }
+}
+
+static bool FunctionParamsAreMainLike(ASTContext &Context,
+                                      const FunctionDecl *FD) {
+  assert(FD->hasPrototype() && "expected the function to have a prototype");
+  const auto *FPT = FD->getType()->castAs<FunctionProtoType>();
+  QualType CharPP =
+      Context.getPointerType(Context.getPointerType(Context.CharTy));
+  QualType Expected[] = {Context.IntTy, CharPP, CharPP, CharPP};
+
+  for (unsigned I = 0; I < FPT->getNumParams(); ++I) {
+    QualType AT = FPT->getParamType(I);
+
+    bool Mismatch = true;
+    if (Context.hasSameUnqualifiedType(AT, Expected[I]))
+      Mismatch = false;
+    else if (Expected[I] == CharPP) {
+      // As an extension, the following forms are okay:
+      //   char const **
+      //   char const * const *
+      //   char * const *
+
+      QualifierCollector Qs;
+      const PointerType *PT;
+      if ((PT = Qs.strip(AT)->getAs<PointerType>()) &&
+          (PT = Qs.strip(PT->getPointeeType())->getAs<PointerType>()) &&
+          Context.hasSameType(QualType(Qs.strip(PT->getPointeeType()), 0),
+                              Context.CharTy)) {
+        Qs.removeConst();
+        Mismatch = !Qs.empty();
+      }
+    }
+
+    if (Mismatch)
+      return false;
----------------
nickdesaulniers wrote:

I think it's possible to express this without `Mismatch`:

```c++
if (!Context.hasSameUnqualifiedType(AT, Expected[I]) && Expected[I] == CharPP) {
  QualifierCollector Qs;
  ...
    if (!Qs.empty())
      return false;
```

https://github.com/llvm/llvm-project/pull/67673


More information about the libc-commits mailing list