summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/AST/ASTContext.h11
-rw-r--r--clang/include/clang/AST/MangleNumberingContext.h19
-rw-r--r--clang/include/clang/Sema/Sema.h2
-rw-r--r--clang/lib/AST/ASTContext.cpp23
-rw-r--r--clang/lib/AST/ItaniumMangle.cpp81
-rw-r--r--clang/lib/AST/MangleNumberingContext.cpp14
-rw-r--r--clang/lib/Sema/SemaDecl.cpp37
-rw-r--r--clang/lib/Sema/SemaLambda.cpp2
-rw-r--r--clang/test/CodeGenCXX/linkage.cpp20
-rw-r--r--clang/test/CodeGenCXX/mangle-local-class-names.cpp31
-rw-r--r--clang/test/CodeGenCXX/mangle.cpp15
11 files changed, 176 insertions, 79 deletions
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 7c2cea25cce..f0b0e41bd0f 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -344,8 +344,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
llvm::DenseMap<const DeclContext *, MangleNumberingContext>
MangleNumberingContexts;
- llvm::DenseMap<const DeclContext *, unsigned> UnnamedMangleContexts;
- llvm::DenseMap<const TagDecl *, unsigned> UnnamedMangleNumbers;
+ /// \brief Side-table of mangling numbers for declarations which rarely
+ /// need them (like static local vars).
+ llvm::DenseMap<const NamedDecl *, unsigned> MangleNumbers;
/// \brief Mapping that stores parameterIndex values for ParmVarDecls when
/// that value exceeds the bitfield size of ParmVarDeclBits.ParameterIndex.
@@ -2086,12 +2087,12 @@ public:
/// it is not used.
bool DeclMustBeEmitted(const Decl *D);
- void addUnnamedTag(const TagDecl *Tag);
- int getUnnamedTagManglingNumber(const TagDecl *Tag) const;
+ void setManglingNumber(const NamedDecl *ND, unsigned Number);
+ unsigned getManglingNumber(const NamedDecl *ND) const;
/// \brief Retrieve the context for computing mangling numbers in the given
/// DeclContext.
- MangleNumberingContext &getManglingNumberContext(DeclContext *DC);
+ MangleNumberingContext &getManglingNumberContext(const DeclContext *DC);
/// \brief Used by ParmVarDecl to store on the side the
/// index of the parameter when it exceeds the size of the normal bitfield.
diff --git a/clang/include/clang/AST/MangleNumberingContext.h b/clang/include/clang/AST/MangleNumberingContext.h
index 35c2abd9d84..4f81e0c5548 100644
--- a/clang/include/clang/AST/MangleNumberingContext.h
+++ b/clang/include/clang/AST/MangleNumberingContext.h
@@ -23,22 +23,35 @@ namespace clang {
class BlockDecl;
class CXXMethodDecl;
+class IdentifierInfo;
+class TagDecl;
class Type;
+class VarDecl;
/// \brief Keeps track of the mangled names of lambda expressions and block
/// literals within a particular context.
class MangleNumberingContext
: public RefCountedBase<MangleNumberingContext> {
llvm::DenseMap<const Type *, unsigned> ManglingNumbers;
-
+ llvm::DenseMap<IdentifierInfo*, unsigned> VarManglingNumbers;
+ llvm::DenseMap<IdentifierInfo*, unsigned> TagManglingNumbers;
+
public:
/// \brief Retrieve the mangling number of a new lambda expression with the
/// given call operator within this context.
- unsigned getManglingNumber(CXXMethodDecl *CallOperator);
+ unsigned getManglingNumber(const CXXMethodDecl *CallOperator);
/// \brief Retrieve the mangling number of a new block literal within this
/// context.
- unsigned getManglingNumber(BlockDecl *BD);
+ unsigned getManglingNumber(const BlockDecl *BD);
+
+ /// \brief Retrieve the mangling number of a static local variable within
+ /// this context.
+ unsigned getManglingNumber(const VarDecl *VD);
+
+ /// \brief Retrieve the mangling number of a static local variable within
+ /// this context.
+ unsigned getManglingNumber(const TagDecl *TD);
};
} // end namespace clang
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 1d780def42d..6345989f160 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -716,7 +716,7 @@ public:
/// \param[out] ManglingContextDecl - Returns the ManglingContextDecl
/// associated with the context, if relevant.
MangleNumberingContext *getCurrentMangleNumberContext(
- DeclContext *DC,
+ const DeclContext *DC,
Decl *&ManglingContextDecl);
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 7f02f59c683..933e5e057ee 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -7990,24 +7990,19 @@ size_t ASTContext::getSideTableAllocatedMemory() const {
+ llvm::capacity_in_bytes(ClassScopeSpecializationPattern);
}
-void ASTContext::addUnnamedTag(const TagDecl *Tag) {
- // FIXME: This mangling should be applied to function local classes too
- if (!Tag->getName().empty() || Tag->getTypedefNameForAnonDecl() ||
- !isa<CXXRecordDecl>(Tag->getParent()))
- return;
-
- std::pair<llvm::DenseMap<const DeclContext *, unsigned>::iterator, bool> P =
- UnnamedMangleContexts.insert(std::make_pair(Tag->getParent(), 0));
- UnnamedMangleNumbers.insert(std::make_pair(Tag, P.first->second++));
+void ASTContext::setManglingNumber(const NamedDecl *ND, unsigned Number) {
+ if (Number > 1)
+ MangleNumbers[ND] = Number;
}
-int ASTContext::getUnnamedTagManglingNumber(const TagDecl *Tag) const {
- llvm::DenseMap<const TagDecl *, unsigned>::const_iterator I =
- UnnamedMangleNumbers.find(Tag);
- return I != UnnamedMangleNumbers.end() ? I->second : -1;
+unsigned ASTContext::getManglingNumber(const NamedDecl *ND) const {
+ llvm::DenseMap<const NamedDecl *, unsigned>::const_iterator I =
+ MangleNumbers.find(ND);
+ return I != MangleNumbers.end() ? I->second : 1;
}
-MangleNumberingContext &ASTContext::getManglingNumberContext(DeclContext *DC) {
+MangleNumberingContext &
+ASTContext::getManglingNumberContext(const DeclContext *DC) {
return MangleNumberingContexts[DC];
}
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index 79219825aae..2dc44eb3555 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -99,7 +99,8 @@ static const unsigned UnknownArity = ~0U;
class ItaniumMangleContext : public MangleContext {
llvm::DenseMap<const TagDecl *, uint64_t> AnonStructIds;
- unsigned Discriminator;
+ typedef std::pair<const DeclContext*, IdentifierInfo*> DiscriminatorKeyTy;
+ llvm::DenseMap<DiscriminatorKeyTy, unsigned> Discriminator;
llvm::DenseMap<const NamedDecl*, unsigned> Uniquifier;
public:
@@ -114,11 +115,6 @@ public:
return Result.first->second;
}
- void startNewFunction() {
- MangleContext::startNewFunction();
- mangleInitDiscriminator();
- }
-
/// @name Mangler Entry Points
/// @{
@@ -153,21 +149,33 @@ public:
void mangleItaniumThreadLocalInit(const VarDecl *D, raw_ostream &);
void mangleItaniumThreadLocalWrapper(const VarDecl *D, raw_ostream &);
- void mangleInitDiscriminator() {
- Discriminator = 0;
- }
-
bool getNextDiscriminator(const NamedDecl *ND, unsigned &disc) {
- // Lambda closure types with external linkage (indicated by a
- // non-zero lambda mangling number) have their own numbering scheme, so
- // they do not need a discriminator.
+ // Lambda closure types are already numbered.
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(ND))
- if (RD->isLambda() && RD->getLambdaManglingNumber() > 0)
+ if (RD->isLambda())
return false;
-
+
+ // Anonymous tags are already numbered.
+ if (const TagDecl *Tag = dyn_cast<TagDecl>(ND)) {
+ if (Tag->getName().empty() && !Tag->getTypedefNameForAnonDecl())
+ return false;
+ }
+
+ // Use the canonical number for externally visible decls.
+ if (ND->isExternallyVisible()) {
+ unsigned discriminator = getASTContext().getManglingNumber(ND);
+ if (discriminator == 1)
+ return false;
+ disc = discriminator - 2;
+ return true;
+ }
+
+ // Make up a reasonable number for internal decls.
unsigned &discriminator = Uniquifier[ND];
- if (!discriminator)
- discriminator = ++Discriminator;
+ if (!discriminator) {
+ const DeclContext *DC = getEffectiveDeclContext(ND);
+ discriminator = ++Discriminator[std::make_pair(DC, ND->getIdentifier())];
+ }
if (discriminator == 1)
return false;
disc = discriminator-2;
@@ -1141,11 +1149,11 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
}
}
- int UnnamedMangle = Context.getASTContext().getUnnamedTagManglingNumber(TD);
- if (UnnamedMangle != -1) {
+ if (TD->isExternallyVisible()) {
+ unsigned UnnamedMangle = getASTContext().getManglingNumber(TD);
Out << "Ut";
- if (UnnamedMangle != 0)
- Out << llvm::utostr(UnnamedMangle - 1);
+ if (UnnamedMangle > 1)
+ Out << llvm::utostr(UnnamedMangle - 2);
Out << '_';
break;
}
@@ -1300,7 +1308,6 @@ void CXXNameMangler::mangleLocalName(const Decl *D) {
// <entity name> will of course contain a <closure-type-name>: Its
// numbering will be local to the particular argument in which it appears
// -- other default arguments do not affect its encoding.
- bool SkipDiscriminator = false;
const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD);
if (CXXRD->isLambda()) {
if (const ParmVarDecl *Parm
@@ -1312,7 +1319,6 @@ void CXXNameMangler::mangleLocalName(const Decl *D) {
if (Num > 1)
mangleNumber(Num - 2);
Out << '_';
- SkipDiscriminator = true;
}
}
}
@@ -1328,24 +1334,21 @@ void CXXNameMangler::mangleLocalName(const Decl *D) {
const NamedDecl *ND = cast<NamedDecl>(D);
mangleNestedName(ND, getEffectiveDeclContext(ND), true /*NoFunction*/);
}
-
- if (!SkipDiscriminator) {
- unsigned disc;
- if (Context.getNextDiscriminator(RD, disc)) {
- if (disc < 10)
- Out << '_' << disc;
- else
- Out << "__" << disc << '_';
- }
+ } else {
+ if (const BlockDecl *BD = dyn_cast<BlockDecl>(D))
+ mangleUnqualifiedBlock(BD);
+ else
+ mangleUnqualifiedName(cast<NamedDecl>(D));
+ }
+ if (const NamedDecl *ND = dyn_cast<NamedDecl>(RD ? RD : D)) {
+ unsigned disc;
+ if (Context.getNextDiscriminator(ND, disc)) {
+ if (disc < 10)
+ Out << '_' << disc;
+ else
+ Out << "__" << disc << '_';
}
-
- return;
}
-
- if (const BlockDecl *BD = dyn_cast<BlockDecl>(D))
- mangleUnqualifiedBlock(BD);
- else
- mangleUnqualifiedName(cast<NamedDecl>(D));
}
void CXXNameMangler::mangleBlockForPrefix(const BlockDecl *Block) {
diff --git a/clang/lib/AST/MangleNumberingContext.cpp b/clang/lib/AST/MangleNumberingContext.cpp
index a4c8a27da5c..4e9006ec24a 100644
--- a/clang/lib/AST/MangleNumberingContext.cpp
+++ b/clang/lib/AST/MangleNumberingContext.cpp
@@ -19,7 +19,7 @@
using namespace clang;
unsigned
-MangleNumberingContext::getManglingNumber(CXXMethodDecl *CallOperator) {
+MangleNumberingContext::getManglingNumber(const CXXMethodDecl *CallOperator) {
const FunctionProtoType *Proto
= CallOperator->getType()->getAs<FunctionProtoType>();
ASTContext &Context = CallOperator->getASTContext();
@@ -31,8 +31,18 @@ MangleNumberingContext::getManglingNumber(CXXMethodDecl *CallOperator) {
}
unsigned
-MangleNumberingContext::getManglingNumber(BlockDecl *BD) {
+MangleNumberingContext::getManglingNumber(const BlockDecl *BD) {
// FIXME: Compute a BlockPointerType? Not obvious how.
const Type *Ty = 0;
return ++ManglingNumbers[Ty];
}
+
+unsigned
+MangleNumberingContext::getManglingNumber(const VarDecl *VD) {
+ return ++VarManglingNumbers[VD->getIdentifier()];
+}
+
+unsigned
+MangleNumberingContext::getManglingNumber(const TagDecl *TD) {
+ return ++TagManglingNumbers[TD->getIdentifier()];
+}
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 3f85de5d2c1..5e535da19a1 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -3043,6 +3043,27 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
return ParsedFreeStandingDeclSpec(S, AS, DS, MultiTemplateParamsArg());
}
+static void HandleTagNumbering(Sema &S, const TagDecl *Tag) {
+ if (isa<CXXRecordDecl>(Tag->getParent())) {
+ // If this tag is the direct child of a class, number it if
+ // it is anonymous.
+ if (!Tag->getName().empty() || Tag->getTypedefNameForAnonDecl())
+ return;
+ MangleNumberingContext &MCtx =
+ S.Context.getManglingNumberContext(Tag->getParent());
+ S.Context.setManglingNumber(Tag, MCtx.getManglingNumber(Tag));
+ return;
+ }
+
+ // If this tag isn't a direct child of a class, number it if it is local.
+ Decl *ManglingContextDecl;
+ if (MangleNumberingContext *MCtx =
+ S.getCurrentMangleNumberContext(Tag->getDeclContext(),
+ ManglingContextDecl)) {
+ S.Context.setManglingNumber(Tag, MCtx->getManglingNumber(Tag));
+ }
+}
+
/// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
/// no declarator (e.g. "struct foo;") is parsed. It also accepts template
/// parameters to cope with template friend declarations.
@@ -3072,7 +3093,7 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
}
if (Tag) {
- getASTContext().addUnnamedTag(Tag);
+ HandleTagNumbering(*this, Tag);
Tag->setFreeStanding();
if (Tag->isInvalidDecl())
return Tag;
@@ -5120,6 +5141,15 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
isIncompleteDeclExternC(*this, NewVD))
RegisterLocallyScopedExternCDecl(NewVD, S);
+ if (NewVD->isStaticLocal()) {
+ Decl *ManglingContextDecl;
+ if (MangleNumberingContext *MCtx =
+ getCurrentMangleNumberContext(NewVD->getDeclContext(),
+ ManglingContextDecl)) {
+ Context.setManglingNumber(NewVD, MCtx->getManglingNumber(NewVD));
+ }
+ }
+
return NewVD;
}
@@ -8374,9 +8404,10 @@ Sema::DeclGroupPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
if (Decl *D = Group[i])
Decls.push_back(D);
- if (DeclSpec::isDeclRep(DS.getTypeSpecType()))
+ if (DeclSpec::isDeclRep(DS.getTypeSpecType())) {
if (const TagDecl *Tag = dyn_cast_or_null<TagDecl>(DS.getRepAsDecl()))
- getASTContext().addUnnamedTag(Tag);
+ HandleTagNumbering(*this, Tag);
+ }
return BuildDeclaratorGroup(Decls, DS.containsPlaceholderType());
}
diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp
index 1e6ef9baf70..8351ff27869 100644
--- a/clang/lib/Sema/SemaLambda.cpp
+++ b/clang/lib/Sema/SemaLambda.cpp
@@ -53,7 +53,7 @@ static bool isInInlineFunction(const DeclContext *DC) {
}
MangleNumberingContext *
-Sema::getCurrentMangleNumberContext(DeclContext *DC,
+Sema::getCurrentMangleNumberContext(const DeclContext *DC,
Decl *&ManglingContextDecl) {
// Compute the context for allocating mangling numbers in the current
// expression, if the ABI requires them.
diff --git a/clang/test/CodeGenCXX/linkage.cpp b/clang/test/CodeGenCXX/linkage.cpp
index 4aba1b32822..cc4e0909c21 100644
--- a/clang/test/CodeGenCXX/linkage.cpp
+++ b/clang/test/CodeGenCXX/linkage.cpp
@@ -12,7 +12,7 @@ namespace test1 {
}
namespace test2 {
- // CHECK-DAG: define internal void @_ZN5test21fIZNS_L1gEvE1S_0EEvT_(
+ // CHECK-DAG: define internal void @_ZN5test21fIZNS_L1gEvE1SEEvT_(
template <typename T> void f(T) {}
static inline void *g() {
struct S {
@@ -46,7 +46,7 @@ namespace test4 {
}
namespace test5 {
- // CHECK-DAG: define linkonce_odr void @_ZN5test51fIZNS_1gILi1EEEPvvE1S_1EEvT_(
+ // CHECK-DAG: define linkonce_odr void @_ZN5test51fIZNS_1gILi1EEEPvvE1SEEvT_(
template <typename T> void f(T) {}
template <int N> inline void *g() {
struct S {
@@ -58,7 +58,7 @@ namespace test5 {
}
namespace test6 {
- // CHECK-DAG: define linkonce_odr void @_ZN5test61fIZZNS_1gEvEN1S1hE_2vE1T_3EEvv(
+ // CHECK-DAG: define linkonce_odr void @_ZN5test61fIZZNS_1gEvEN1S1hEvE1TEEvv(
template <typename T> void f() {}
inline void *g() {
@@ -76,7 +76,7 @@ namespace test6 {
}
namespace test7 {
- // CHECK-DAG: define internal void @_ZN5test71fIZZNS_1gEvEN1S1hEvE1T_4EEvv(
+ // CHECK-DAG: define internal void @_ZN5test71fIZZNS_1gEvEN1S1hEvE1TEEvv(
template <typename T> void f() {}
void *g() {
@@ -105,7 +105,7 @@ namespace test8 {
}
namespace test9 {
- // CHECK-DAG: define linkonce_odr void @_ZN5test91fIPZNS_1gEvE1S_5EEvT_(
+ // CHECK-DAG: define linkonce_odr void @_ZN5test91fIPZNS_1gEvE1SEEvT_(
template <typename T> void f(T) {}
inline void *g() {
struct S {
@@ -116,7 +116,7 @@ namespace test9 {
}
namespace test10 {
- // CHECK-DAG: define linkonce_odr void @_ZN6test101fIPFZNS_1gEvE1S_6vEEEvT_(
+ // CHECK-DAG: define linkonce_odr void @_ZN6test101fIPFZNS_1gEvE1SvEEEvT_(
template <typename T> void f(T) {}
inline void *g() {
struct S {
@@ -128,7 +128,7 @@ namespace test10 {
}
namespace test11 {
- // CHECK-DAG: define internal void @_ZN6test111fIPFZNS_1gEvE1S_7PNS_12_GLOBAL__N_11IEEEEvT_(
+ // CHECK-DAG: define internal void @_ZN6test111fIPFZNS_1gEvE1SPNS_12_GLOBAL__N_11IEEEEvT_(
namespace {
struct I {
};
@@ -172,7 +172,7 @@ namespace test13 {
}
namespace test14 {
- // CHECK-DAG: define linkonce_odr void @_ZN6test143fooIZNS_1fEvE1S_8E3barILPS1_0EEEvv(
+ // CHECK-DAG: define linkonce_odr void @_ZN6test143fooIZNS_1fEvE1SE3barILPS1_0EEEvv(
template <typename T> struct foo {
template <T *P> static void bar() {}
static void *g() { return (void *)bar<nullptr>; }
@@ -186,7 +186,7 @@ namespace test14 {
}
namespace test15 {
- // CHECK-DAG: define linkonce_odr void @_ZN6test153zedIZNS_3fooIiEEPvvE3bar_9EEvv(
+ // CHECK-DAG: define linkonce_odr void @_ZN6test153zedIZNS_3fooIiEEPvvE3barEEvv(
template <class T> void zed() {}
template <class T> void *foo() {
class bar {
@@ -197,7 +197,7 @@ namespace test15 {
}
namespace test16 {
- // CHECK-DAG: define linkonce_odr void @_ZN6test163zedIZNS_3fooIiE3barEvE1S__10_EEvv(
+ // CHECK-DAG: define linkonce_odr void @_ZN6test163zedIZNS_3fooIiE3barEvE1SEEvv(
template <class T> void zed() {}
template <class T> struct foo {
static void *bar();
diff --git a/clang/test/CodeGenCXX/mangle-local-class-names.cpp b/clang/test/CodeGenCXX/mangle-local-class-names.cpp
index c3ea31a54ca..186d76a225a 100644
--- a/clang/test/CodeGenCXX/mangle-local-class-names.cpp
+++ b/clang/test/CodeGenCXX/mangle-local-class-names.cpp
@@ -55,6 +55,26 @@ void GORF (float IVAR1)
}
}
+// CHECK: @_ZZ12OmittingCodefEN4SSSSC1E_0RKf
+inline void OmittingCode(float x) {
+ if (0) {
+ struct SSSS {
+ float bv;
+ SSSS(const float& from): bv(from) { }
+ };
+
+ SSSS VAR1(x);
+ }
+
+ struct SSSS {
+ float bv;
+ SSSS(const float& from): bv(from) { }
+ };
+
+ SSSS VAR2(x);
+}
+void CallOmittingCode() { OmittingCode(1); }
+
// CHECK: @_ZZ25LocalTemplateFunctionTestdEN5Local3fooIdEET_S1_
int LocalTemplateFunctionTest(double d) {
struct Local {
@@ -64,3 +84,14 @@ int LocalTemplateFunctionTest(double d) {
};
return Local().foo(d);
}
+
+// CHECK: @_ZZ15LocalAnonStructvENUt0_1gEv
+inline void LocalAnonStruct() {
+ if (0) {
+ struct { void f() {} } x;
+ x.f();
+ }
+ struct { void g() {} } y;
+ y.g();
+}
+void CallLocalAnonStruct() { LocalAnonStruct(); }
diff --git a/clang/test/CodeGenCXX/mangle.cpp b/clang/test/CodeGenCXX/mangle.cpp
index 5f31e5480d2..4b601229d34 100644
--- a/clang/test/CodeGenCXX/mangle.cpp
+++ b/clang/test/CodeGenCXX/mangle.cpp
@@ -888,7 +888,7 @@ namespace test38 {
}
namespace test39 {
- // CHECK: define internal void @"_ZN6test394funcINS_3$_0Ut_EEEvT_"
+ // CHECK: define internal void @"_ZN6test394funcINS_3$_03$_1EEEvT_"
typedef struct {
struct {} a;
} *foo;
@@ -897,3 +897,16 @@ namespace test39 {
func(x->a);
}
}
+
+namespace test40 {
+ // CHECK: i32* @_ZZN6test401fEvE1a_0
+ void h(int&);
+ inline void f() {
+ if (0) {
+ static int a;
+ }
+ static int a;
+ h(a);
+ };
+ void g() { f(); }
+}
OpenPOWER on IntegriCloud