Skip to content

Commit 972f0d9

Browse files
C++: Stop generating NoOp instructions for declarations of externs
Previously, where we had a function-scoped `DeclarationEntry` for an extern variable or function, we would generate a `NoOp` instruction for it. There's nothing wrong with this by itself, although it was unnecessary. However, I've hit an extractor issue (Jira ticket already opened) that commonly causes multiple `DeclStmt`s to share a single `DeclarationEntry` child on extern declarations, so removing the `NoOp` instructions is an easy way to work around the extractor issue.
1 parent 07fa55f commit 972f0d9

File tree

4 files changed

+67
-10
lines changed

4 files changed

+67
-10
lines changed

cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ abstract class TranslatedDeclarationEntry extends TranslatedElement, TTranslated
4747
/**
4848
* Represents the IR translation of a declaration within the body of a function,
4949
* for declarations other than local variables. Since these have no semantic
50-
* effect, they are translated as `NoOp`.
50+
* effect, they do not generate any instructions.
5151
*/
5252
class TranslatedNonVariableDeclarationEntry extends TranslatedDeclarationEntry {
5353
TranslatedNonVariableDeclarationEntry() {
@@ -56,25 +56,20 @@ class TranslatedNonVariableDeclarationEntry extends TranslatedDeclarationEntry {
5656

5757
override predicate hasInstruction(Opcode opcode, InstructionTag tag,
5858
Type resultType, boolean isGLValue) {
59-
opcode instanceof Opcode::NoOp and
60-
tag = OnlyInstructionTag() and
61-
resultType instanceof VoidType and
62-
isGLValue = false
59+
none()
6360
}
6461

6562
override Instruction getFirstInstruction() {
66-
result = getInstruction(OnlyInstructionTag())
63+
result = getParent().getChildSuccessor(this)
6764
}
6865

6966
override TranslatedElement getChild(int id) {
7067
none()
7168
}
7269

7370
override Instruction getInstructionSuccessor(InstructionTag tag,
74-
EdgeKind kind) {
75-
tag = OnlyInstructionTag() and
76-
result = getParent().getChildSuccessor(this) and
77-
kind instanceof GotoEdge
71+
EdgeKind kind) {
72+
none()
7873
}
7974

8075
override Instruction getChildSuccessor(TranslatedElement child) {

cpp/ql/test/library-tests/ir/ir/PrintAST.expected

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7828,3 +7828,40 @@ ir.cpp:
78287828
# 1109| Type = [LValueReferenceType] unsigned int &
78297829
# 1109| ValueCategory = prvalue(load)
78307830
# 1111| 1: [ReturnStmt] return ...
7831+
# 1113| [TopLevelFunction] void ExternDeclarations()
7832+
# 1113| params:
7833+
# 1114| body: [Block] { ... }
7834+
# 1115| 0: [DeclStmt] declaration
7835+
# 1115| 0: [VariableDeclarationEntry] declaration of g
7836+
# 1115| Type = [IntType] int
7837+
# 1116| 1: [DeclStmt] declaration
7838+
# 1116| 0: [VariableDeclarationEntry] definition of x
7839+
# 1116| Type = [IntType] int
7840+
# 1117| 2: [DeclStmt] declaration
7841+
# 1117| 0: [VariableDeclarationEntry] definition of y
7842+
# 1117| Type = [IntType] int
7843+
# 1117| 1: [FunctionDeclarationEntry] declaration of f
7844+
# 1117| Type = [IntType] int
7845+
# 1118| 3: [DeclStmt] declaration
7846+
# 1118| 0: [FunctionDeclarationEntry] declaration of z
7847+
# 1118| Type = [IntType] int
7848+
# 1118| 1: [FunctionDeclarationEntry] declaration of w
7849+
# 1118| Type = [IntType] int
7850+
# 1118| 2: [VariableDeclarationEntry] definition of h
7851+
# 1118| Type = [IntType] int
7852+
# 1119| 4: [DeclStmt] declaration
7853+
# 1119| 0: [TypeDeclarationEntry] declaration of d
7854+
# 1119| Type = [LocalTypedefType] d
7855+
# 1120| 5: [ReturnStmt] return ...
7856+
# 1117| [TopLevelFunction] int f(float)
7857+
# 1117| params:
7858+
# 1117| 0: [Parameter] p#0
7859+
# 1117| Type = [FloatType] float
7860+
# 1118| [TopLevelFunction] int z(float)
7861+
# 1118| params:
7862+
# 1118| 0: [Parameter] p#0
7863+
# 1118| Type = [FloatType] float
7864+
# 1118| [TopLevelFunction] int w(float)
7865+
# 1118| params:
7866+
# 1118| 0: [Parameter] p#0
7867+
# 1118| Type = [FloatType] float

cpp/ql/test/library-tests/ir/ir/ir.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1110,4 +1110,13 @@ static void AsmStmtWithOutputs(unsigned int& a, unsigned int& b, unsigned int& c
11101110
);
11111111
}
11121112

1113+
void ExternDeclarations()
1114+
{
1115+
extern int g;
1116+
int x;
1117+
int y, f(float);
1118+
int z(float), w(float), h;
1119+
typedef double d;
1120+
}
1121+
11131122
// semmle-extractor-options: -std=c++17

cpp/ql/test/library-tests/ir/ir/raw_ir.expected

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5112,3 +5112,19 @@ ir.cpp:
51125112
# 1104| v0_17(void) = ReturnVoid :
51135113
# 1104| v0_18(void) = UnmodeledUse : mu*
51145114
# 1104| v0_19(void) = ExitFunction :
5115+
5116+
# 1113| void ExternDeclarations()
5117+
# 1113| Block 0
5118+
# 1113| v0_0(void) = EnterFunction :
5119+
# 1113| mu0_1(unknown) = AliasedDefinition :
5120+
# 1113| mu0_2(unknown) = UnmodeledDefinition :
5121+
# 1116| r0_3(glval<int>) = VariableAddress[x] :
5122+
# 1116| mu0_4(int) = Uninitialized[x] : &:r0_3
5123+
# 1117| r0_5(glval<int>) = VariableAddress[y] :
5124+
# 1117| mu0_6(int) = Uninitialized[y] : &:r0_5
5125+
# 1118| r0_7(glval<int>) = VariableAddress[h] :
5126+
# 1118| mu0_8(int) = Uninitialized[h] : &:r0_7
5127+
# 1120| v0_9(void) = NoOp :
5128+
# 1113| v0_10(void) = ReturnVoid :
5129+
# 1113| v0_11(void) = UnmodeledUse : mu*
5130+
# 1113| v0_12(void) = ExitFunction :

0 commit comments

Comments
 (0)