diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10176,6 +10176,9 @@ "argument to __builtin_longjmp must be a constant 1">; def err_builtin_requires_language : Error<"'%0' is only available in %1">; +def err_builtin_dump_struct_too_complex : Error< +"%select{class|struct|union}0 %1 is too complex to dump">; + def err_constant_integer_arg_type : Error< "argument to %0 must be a constant integer">; diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -724,6 +724,16 @@ if (Generator.dumpUnnamedRecord(RD, PtrArg, 0)) return ExprError(); + // We create a `PseudoObjectExpr` as a wrapper, but the + // `PseudoObjectExprBits.NumSubExprs` in `PseudoObjectExpr` restricts its + // value to no more than std::numeric_limits::max(). + if (Generator.Actions.size() > std::numeric_limits::max()) { + int RDKind = RD->isClass() ? 0 : (RD->isStruct() ? 1 : 2); + S.Diag(PtrArg->getBeginLoc(), diag::err_builtin_dump_struct_too_complex) + << RDKind << RD; + return ExprError(); + } + return Generator.buildWrapper(); } diff --git a/clang/test/SemaCXX/builtin-dump-struct.cpp b/clang/test/SemaCXX/builtin-dump-struct.cpp --- a/clang/test/SemaCXX/builtin-dump-struct.cpp +++ b/clang/test/SemaCXX/builtin-dump-struct.cpp @@ -184,3 +184,22 @@ int printf(const char *, ...); void f1(t2 w) { __builtin_dump_struct(&w, printf); } + +struct t3 { }; +template +struct templ { + T1 v1; + T1 v2; + T1 v3; + T1 v4; +}; + +struct t4 { + templ>>>>> c0; + templ>>>>> c1; + templ>>>>> c2; +}; + +void aj(...); +void f2(t4 w) { __builtin_dump_struct(&w, aj); } // expected-error{{struct 't4' is too complex to dump}} +