diff --git a/ClangVisitor.cpp b/ClangVisitor.cpp index 4192305f01feeb9914e9664d7238c65c3a439b61..a56c9223a8cae6004e5dc6988ae6653b7775a87e 100644 --- a/ClangVisitor.cpp +++ b/ClangVisitor.cpp @@ -2245,8 +2245,8 @@ exp_node FramacVisitor::makeDeclRefExpression( assert (llvm::dyn_cast<clang::EnumType const>(t)); const clang::EnumType* enumType = static_cast<const clang::EnumType*>(t.getTypePtr()); + const clang::EnumDecl* declEnum = enumType->getDecl(); if (hasInstanceContext()) { - const clang::EnumDecl* declEnum = enumType->getDecl(); if (!_tableForWaitingDeclarations.hasVisited(declEnum)) unvisitedDecls().push_back(declEnum); else { @@ -2266,7 +2266,9 @@ exp_node FramacVisitor::makeDeclRefExpression( exp_node_Constant( compilation_constant_EnumCst( _clangUtils->makeQualifiedName(*variableExpr->getDecl()), - ekind_cons(_clangUtils->makeQualifiedName(*enumType->getDecl())), + ekind_cons( + _clangUtils->makeQualifiedName(*declEnum), + Clang_utils::isExternCContext(enumType->getDecl())), (int64_t)enumDecl->getInitVal().getLimitedValue(UINT64_MAX))), variableExpr); } @@ -7810,6 +7812,7 @@ bool FramacVisitor::VisitEnumDecl(clang::EnumDecl* Decl) { readGlobalComment(Decl, true /* mayHaveTemplate */); qualified_name enumName = _clangUtils->makeQualifiedName(*Decl); bool isFirstEnumName = true; + bool isExternC = Clang_utils::isExternCContext(Decl); const char* name = strdup(enumName->decl_name); // if (!_parents.hasLexicalContext()) // name = copy_string(Decl->getQualifiedNameAsString()); @@ -7824,8 +7827,9 @@ bool FramacVisitor::VisitEnumDecl(clang::EnumDecl* Decl) { qualified_name itemName = _clangUtils->makeQualifiedName(**enumIter); compilation_constant newEnum = compilation_constant_EnumCst( - itemName, ekind_cons(isFirstEnumName ? enumName - : qualified_name_dup(enumName)), + itemName, + ekind_cons( + isFirstEnumName ? enumName : qualified_name_dup(enumName),isExternC), (int64_t) enumIter->getInitVal().getLimitedValue(UINT64_MAX)); isFirstEnumName = false; forwardEnums.insertContainer(newEnum); diff --git a/Clang_utils.cpp b/Clang_utils.cpp index 57307ba52b85a22513cc1af4cd984e0f31fe694f..d48e932b60ca3695d4206859d585f18a5a0ceac6 100644 --- a/Clang_utils.cpp +++ b/Clang_utils.cpp @@ -1679,12 +1679,13 @@ Clang_utils::makePlainType( if (declRegistration && declRegistration->doesRegisterDecl()) declRegistration->registerDecl(enumType->getDecl()); qualified_name name; - if (!isPOD || !Clang_utils::isExternCContext(enumType->getDecl())) + bool extern_c = Clang_utils::isExternCContext(enumType->getDecl()); + if (!isPOD || !extern_c) name = makeQualifiedName(*enumType->getDecl()); else name = qualified_name_cons(NULL, copy_string(enumType->getDecl()->getName().str())); - return typ_Enum(ekind_cons(name)); + return typ_Enum(ekind_cons(name,extern_c)); }; case clang::Type::Auto: { assert(llvm::dyn_cast<const clang::AutoType>(type)); diff --git a/convert.ml b/convert.ml index ff576e38ff36c6ef074c64b55fb1c11b9824139f..bde251ecd6cd47e31a24a4232d2c0b55d7c64402 100644 --- a/convert.ml +++ b/convert.ml @@ -609,7 +609,11 @@ let rec convert_base_type env spec decl typ does_remove_virtual = | Float FLongDouble -> (List.map spec_type [Tlong; Tdouble]) @ spec, decl | Enum e -> let body_name, t = Convert_env.typedef_normalize env e.body TStandard in - spec_type (Tenum(Mangling.mangle body_name t None,None,[]))::spec, decl + let name = + if e.ekind_is_extern_c then body_name.decl_name + else Mangling.mangle body_name t None + in + spec_type (Tenum(name,None,[]))::spec, decl | Struct (s,t) -> let name = if Convert_env.is_extern_c_aggregate env s t then s.decl_name @@ -764,9 +768,14 @@ and convert_constant env c does_remove_virtual = match c with | FloatCst(_,v) -> CONSTANT(CONST_FLOAT v) | EnumCst(n,e,_) -> let n, t = Convert_env.typedef_normalize env n TStandard in - let name = Mangling.mangle n t None in + let name = + if e.ekind_is_extern_c then n.decl_name else Mangling.mangle n t None + in let body_name, t' = Convert_env.typedef_normalize env e.body TStandard in - let enum = Mangling.mangle body_name t' None in + let enum = + if e.ekind_is_extern_c then body_name.decl_name + else Mangling.mangle body_name t' None + in (* C++ enum constant are of type Enum, while C treat them as integers. This is not an issue for most purposes, except when it comes to handle exceptions: catching enum e is not the same as catching int x. @@ -2459,10 +2468,12 @@ and convert_stmt_list env l does_remove_virtual = let convert_enum_constant env ikind e = let loc = Convert_env.get_loc env in match e with - | EnumCst(name,_,value) -> - let name, t - = Convert_env.typedef_normalize env name TStandard in - let name = Mangling.mangle name t None in + | EnumCst(name,e,value) -> + let name, t = Convert_env.typedef_normalize env name TStandard in + let name = + if e.ekind_is_extern_c then name.decl_name + else Mangling.mangle name t None + in (* If the value is negative, create an expression with a positive value. *) let value = diff --git a/intermediate_format.ast b/intermediate_format.ast index fbfeb6abae86ecb4450f5512ff5eb5e4c1b5cb69..ccdb1c346fa714224886bc5e00a56f29a7680dc9 100644 --- a/intermediate_format.ast +++ b/intermediate_format.ast @@ -100,7 +100,10 @@ type qualified_name = | _ -> x" ;; -type ekind = { body: qualified_name; } +type ekind = { + body: qualified_name; + is_extern_c: bool; +} ;; type funkind = diff --git a/tests/basic/oracle/extern.res.oracle b/tests/basic/oracle/extern.res.oracle index 5e6aeff87b48b0e5fd623b309985168f93b2bb62..3d8d83014b84b3d297423cff0de414861601a2e9 100644 --- a/tests/basic/oracle/extern.res.oracle +++ b/tests/basic/oracle/extern.res.oracle @@ -6,9 +6,15 @@ struct A; struct B { int x ; }; +enum E { + TAG1 = 0U, + TAG2 = 1U, + TAG3 = 2U +}; struct C { int y ; }; +enum E e1 = (enum E)TAG2; int f(struct A *x) { int __retres;