diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp --- a/clang/lib/Analysis/CFG.cpp +++ b/clang/lib/Analysis/CFG.cpp @@ -2839,11 +2839,24 @@ /// DeclStmts and initializers in them. CFGBlock *CFGBuilder::VisitDeclSubExpr(DeclStmt *DS) { assert(DS->isSingleDecl() && "Can handle single declarations only."); + + if (const auto *TDD = dyn_cast(DS->getSingleDecl())) { + // If we encounter a VLA in typedef, then process its size expressions. + CFGBlock *LastBlock = Block; + for (const VariableArrayType *VA = + FindVA(TDD->getUnderlyingType().getTypePtr()); + VA != nullptr; VA = FindVA(VA->getElementType().getTypePtr())) { + if (CFGBlock *newBlock = addStmt(VA->getSizeExpr())) + LastBlock = newBlock; + } + return LastBlock; + } + VarDecl *VD = dyn_cast(DS->getSingleDecl()); if (!VD) { - // Of everything that can be declared in a DeclStmt, only VarDecls impact - // runtime semantics. + // Of everything that can be declared in a DeclStmt, only VarDecls and the + // exceptions above impact runtime semantics. return Block; } diff --git a/clang/test/Analysis/cfg.cpp b/clang/test/Analysis/cfg.cpp --- a/clang/test/Analysis/cfg.cpp +++ b/clang/test/Analysis/cfg.cpp @@ -568,6 +568,25 @@ return 2; } +// CHECK-LABEL: void vla_simple(int x) +// CHECK: [B1] +// CHECK-NEXT: 1: x +// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: 3: int vla[x]; +void vla_simple(int x) { + int vla[x]; +} + +// CHECK-LABEL: void vla_typedef(int x) +// CHECK: [B1] +// CHECK-NEXT: 1: x +// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: 3: VLA vla; +void vla_typedef(int x) { + typedef int VLA[x]; + VLA vla; +} + // CHECK-LABEL: template<> int *PR18472() // CHECK: [B2 (ENTRY)] // CHECK-NEXT: Succs (1): B1