arichardson created this revision.
arichardson added reviewers: courbet, Quuxplusone, aaron.ballman.
arichardson requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Trying to debug a static_assert(offset(foo, field) == ...) failure can be
rather awkward since there is no easy way to print the value at compile
time without another compiler diagnostic involving an array size.
This builds upon the sizeof()/alignof() printing and extends it to handle
OffsetOfExpr.

Depends on D108211 <https://reviews.llvm.org/D108211>


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D108212

Files:
  clang/lib/Sema/SemaTemplate.cpp
  clang/test/SemaCXX/static-assert.cpp


Index: clang/test/SemaCXX/static-assert.cpp
===================================================================
--- clang/test/SemaCXX/static-assert.cpp
+++ clang/test/SemaCXX/static-assert.cpp
@@ -216,3 +216,10 @@
 // expected-error@-1{{static_assert failed due to requirement 
'alignof(IntAndPointer) == sizeof(IntAndPointer)' "message"}}
 // expected-note@-2{{with 'alignof(IntAndPointer)' equal to 8}}
 // expected-note@-3{{with 'sizeof(IntAndPointer)' equal to 16}}
+#define offsetof(s, f) __builtin_offsetof(s, f)
+static_assert(__builtin_offsetof(IntAndPointer, p) == -1, "message");
+// expected-error@-1{{static_assert failed due to requirement 
'__builtin_offsetof(IntAndPointer, p) == -1' "message"}}
+// expected-note@-2{{with '__builtin_offsetof(IntAndPointer, p)' equal to 8}}
+static_assert(offsetof(IntAndPointer, i) == -1, "message");
+// expected-error@-1{{static_assert failed due to requirement 
'__builtin_offsetof(IntAndPointer, i) == -1' "message"}}
+// expected-note@-2{{with '__builtin_offsetof(IntAndPointer, i)' equal to 0}}
Index: clang/lib/Sema/SemaTemplate.cpp
===================================================================
--- clang/lib/Sema/SemaTemplate.cpp
+++ clang/lib/Sema/SemaTemplate.cpp
@@ -3577,10 +3577,10 @@
   explicit FailedBooleanConditionPrinterHelper(
       const PrintingPolicy &P, Sema &S,
       SmallVectorImpl<PartialDiagnosticAt> &Notes)
-      : Policy(P), S(S), Notes(Notes) {}
+      : Policy(P), SemaRef(S), Notes(Notes) {}
 
-  bool handledStmt(Stmt *E, raw_ostream &OS) override {
-    const auto *DR = dyn_cast<DeclRefExpr>(E);
+  bool handledStmt(Stmt *S, raw_ostream &OS) override {
+    const auto *DR = dyn_cast<DeclRefExpr>(S);
     if (DR && DR->getQualifier()) {
       // If this is a qualified name, expand the template arguments in nested
       // qualifiers.
@@ -3595,18 +3595,20 @@
             IV->getSpecializedTemplate()->getTemplateParameters());
       }
       return true;
-    } else if (auto *UE = dyn_cast<UnaryExprOrTypeTraitExpr>(E)) {
+    } else if (isa<UnaryExprOrTypeTraitExpr>(S) || isa<OffsetOfExpr>(S)) {
+      Expr *E = cast<Expr>(S);
       Expr::EvalResult Result;
-      if (UE->EvaluateAsConstantExpr(Result, S.Context) && Result.Val.isInt()) 
{
+      if (E->EvaluateAsConstantExpr(Result, SemaRef.Context) &&
+          Result.Val.isInt()) {
         std::string ExprStr;
         llvm::raw_string_ostream ExprStream(ExprStr);
-        UE->printPretty(ExprStream, nullptr, Policy);
+        E->printPretty(ExprStream, nullptr, Policy);
         ExprStream.flush();
         Notes.push_back(PartialDiagnosticAt(
-            UE->getExprLoc(),
-            S.PDiag(diag::note_static_assert_requirement_context)
+            E->getExprLoc(),
+            SemaRef.PDiag(diag::note_static_assert_requirement_context)
                 << ExprStr << toString(Result.Val.getInt(), 10)
-                << UE->getSourceRange()));
+                << E->getSourceRange()));
       }
     }
     return false;
@@ -3614,7 +3616,7 @@
 
 private:
   const PrintingPolicy Policy;
-  Sema &S;
+  Sema &SemaRef;
   SmallVectorImpl<PartialDiagnosticAt> &Notes;
 };
 


Index: clang/test/SemaCXX/static-assert.cpp
===================================================================
--- clang/test/SemaCXX/static-assert.cpp
+++ clang/test/SemaCXX/static-assert.cpp
@@ -216,3 +216,10 @@
 // expected-error@-1{{static_assert failed due to requirement 'alignof(IntAndPointer) == sizeof(IntAndPointer)' "message"}}
 // expected-note@-2{{with 'alignof(IntAndPointer)' equal to 8}}
 // expected-note@-3{{with 'sizeof(IntAndPointer)' equal to 16}}
+#define offsetof(s, f) __builtin_offsetof(s, f)
+static_assert(__builtin_offsetof(IntAndPointer, p) == -1, "message");
+// expected-error@-1{{static_assert failed due to requirement '__builtin_offsetof(IntAndPointer, p) == -1' "message"}}
+// expected-note@-2{{with '__builtin_offsetof(IntAndPointer, p)' equal to 8}}
+static_assert(offsetof(IntAndPointer, i) == -1, "message");
+// expected-error@-1{{static_assert failed due to requirement '__builtin_offsetof(IntAndPointer, i) == -1' "message"}}
+// expected-note@-2{{with '__builtin_offsetof(IntAndPointer, i)' equal to 0}}
Index: clang/lib/Sema/SemaTemplate.cpp
===================================================================
--- clang/lib/Sema/SemaTemplate.cpp
+++ clang/lib/Sema/SemaTemplate.cpp
@@ -3577,10 +3577,10 @@
   explicit FailedBooleanConditionPrinterHelper(
       const PrintingPolicy &P, Sema &S,
       SmallVectorImpl<PartialDiagnosticAt> &Notes)
-      : Policy(P), S(S), Notes(Notes) {}
+      : Policy(P), SemaRef(S), Notes(Notes) {}
 
-  bool handledStmt(Stmt *E, raw_ostream &OS) override {
-    const auto *DR = dyn_cast<DeclRefExpr>(E);
+  bool handledStmt(Stmt *S, raw_ostream &OS) override {
+    const auto *DR = dyn_cast<DeclRefExpr>(S);
     if (DR && DR->getQualifier()) {
       // If this is a qualified name, expand the template arguments in nested
       // qualifiers.
@@ -3595,18 +3595,20 @@
             IV->getSpecializedTemplate()->getTemplateParameters());
       }
       return true;
-    } else if (auto *UE = dyn_cast<UnaryExprOrTypeTraitExpr>(E)) {
+    } else if (isa<UnaryExprOrTypeTraitExpr>(S) || isa<OffsetOfExpr>(S)) {
+      Expr *E = cast<Expr>(S);
       Expr::EvalResult Result;
-      if (UE->EvaluateAsConstantExpr(Result, S.Context) && Result.Val.isInt()) {
+      if (E->EvaluateAsConstantExpr(Result, SemaRef.Context) &&
+          Result.Val.isInt()) {
         std::string ExprStr;
         llvm::raw_string_ostream ExprStream(ExprStr);
-        UE->printPretty(ExprStream, nullptr, Policy);
+        E->printPretty(ExprStream, nullptr, Policy);
         ExprStream.flush();
         Notes.push_back(PartialDiagnosticAt(
-            UE->getExprLoc(),
-            S.PDiag(diag::note_static_assert_requirement_context)
+            E->getExprLoc(),
+            SemaRef.PDiag(diag::note_static_assert_requirement_context)
                 << ExprStr << toString(Result.Val.getInt(), 10)
-                << UE->getSourceRange()));
+                << E->getSourceRange()));
       }
     }
     return false;
@@ -3614,7 +3616,7 @@
 
 private:
   const PrintingPolicy Policy;
-  Sema &S;
+  Sema &SemaRef;
   SmallVectorImpl<PartialDiagnosticAt> &Notes;
 };
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to