[clang][ExtractAPI] Fix up casting from CXXClassRecord (#110983)

`RecordRecord::classOfKind` and `TagRecord::classofKind` didn't
correctly capture `RK_CXXClass` and derived variants, e.g.
`RK_ClassTemplate`. This materialized by anonymous C++ tag types not
being correctly detected when they need to be merged with another
record.
This commit is contained in:
Daniel Grumberg
2024-10-16 09:45:43 +01:00
committed by GitHub
parent 5059059c7b
commit 949177dabc
3 changed files with 82 additions and 26 deletions

View File

@@ -26,6 +26,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
#include "llvm/TargetParser/Triple.h"
#include <cstddef>
#include <iterator>
@@ -615,7 +616,24 @@ struct TagRecord : APIRecord, RecordContext {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) {
return K == RK_Struct || K == RK_Union || K == RK_Enum;
switch (K) {
case RK_Enum:
LLVM_FALLTHROUGH;
case RK_Struct:
LLVM_FALLTHROUGH;
case RK_Union:
LLVM_FALLTHROUGH;
case RK_CXXClass:
LLVM_FALLTHROUGH;
case RK_ClassTemplate:
LLVM_FALLTHROUGH;
case RK_ClassTemplateSpecialization:
LLVM_FALLTHROUGH;
case RK_ClassTemplatePartialSpecialization:
return true;
default:
return false;
}
}
bool IsEmbeddedInVarDeclarator;
@@ -684,7 +702,22 @@ struct RecordRecord : TagRecord {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) {
return K == RK_Struct || K == RK_Union;
switch (K) {
case RK_Struct:
LLVM_FALLTHROUGH;
case RK_Union:
LLVM_FALLTHROUGH;
case RK_CXXClass:
LLVM_FALLTHROUGH;
case RK_ClassTemplate:
LLVM_FALLTHROUGH;
case RK_ClassTemplateSpecialization:
LLVM_FALLTHROUGH;
case RK_ClassTemplatePartialSpecialization:
return true;
default:
return false;
}
}
bool isAnonymousWithNoTypedef() { return Name.empty(); }

View File

@@ -1,11 +1,18 @@
// RUN: rm -rf %t
// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \
// RUN: -triple arm64-apple-macosx -isystem %S -fretain-comments-from-system-headers \
// RUN: -x c-header %s -o %t/output.symbols.json -verify
// RUN: -x c-header %s -o %t/output-c.symbols.json -verify
//
// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \
// RUN: -triple arm64-apple-macosx -isystem %S -fretain-comments-from-system-headers \
// RUN: -x c++-header %s -o %t/output-cxx.symbols.json -verify
// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix GLOBAL
// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix PREFIX
// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix CONTENT
// RUN: FileCheck %s --input-file %t/output-c.symbols.json --check-prefix GLOBAL
// RUN: FileCheck %s --input-file %t/output-c.symbols.json --check-prefix PREFIX
// RUN: FileCheck %s --input-file %t/output-c.symbols.json --check-prefix CONTENT
// RUN: FileCheck %s --input-file %t/output-cxx.symbols.json --check-prefix GLOBAL
// RUN: FileCheck %s --input-file %t/output-cxx.symbols.json --check-prefix PREFIX
// RUN: FileCheck %s --input-file %t/output-cxx.symbols.json --check-prefix CONTENT
/// A global variable with an anonymous struct type.
struct { char *prefix; char *content; } global;
// GLOBAL-LABEL: "!testLabel": "c:@global"
@@ -30,7 +37,7 @@ struct { char *prefix; char *content; } global;
// GLOBAL: "text": "A global variable with an anonymous struct type."
// GLOBAL: "kind": {
// GLOBAL-NEXT: "displayName": "Global Variable",
// GLOBAL-NEXT: "identifier": "c.var"
// GLOBAL-NEXT: "identifier": "c{{(\+\+)?}}.var"
// GLOBAL: "title": "global"
// GLOBAL: "pathComponents": [
// GLOBAL-NEXT: "global"
@@ -54,9 +61,12 @@ struct { char *prefix; char *content; } global;
/// A Vehicle
struct Vehicle {
// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix TYPE
// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix BICYCLE
// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix CAR
// RUN: FileCheck %s --input-file %t/output-c.symbols.json --check-prefix TYPE
// RUN: FileCheck %s --input-file %t/output-c.symbols.json --check-prefix BICYCLE
// RUN: FileCheck %s --input-file %t/output-c.symbols.json --check-prefix CAR
// RUN: FileCheck %s --input-file %t/output-cxx.symbols.json --check-prefix TYPE
// RUN: FileCheck %s --input-file %t/output-cxx.symbols.json --check-prefix BICYCLE
// RUN: FileCheck %s --input-file %t/output-cxx.symbols.json --check-prefix CAR
/// The type of vehicle.
enum {
Bicycle,
@@ -96,9 +106,12 @@ struct Vehicle {
// CAR-NEXT: "Car"
// CAR-NEXT: ]
// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix INFORMATION
// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix WHEELS
// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix NAME
// RUN: FileCheck %s --input-file %t/output-c.symbols.json --check-prefix INFORMATION
// RUN: FileCheck %s --input-file %t/output-c.symbols.json --check-prefix WHEELS
// RUN: FileCheck %s --input-file %t/output-c.symbols.json --check-prefix NAME
// RUN: FileCheck %s --input-file %t/output-cxx.symbols.json --check-prefix INFORMATION
// RUN: FileCheck %s --input-file %t/output-cxx.symbols.json --check-prefix WHEELS
// RUN: FileCheck %s --input-file %t/output-cxx.symbols.json --check-prefix NAME
/// The information about the vehicle.
union {
int wheels;
@@ -145,8 +158,10 @@ struct Vehicle {
// NAME-NEXT: ]
};
// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix GLOBALCASE
// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix GLOBALOTHERCASE
// RUN: FileCheck %s --input-file %t/output-c.symbols.json --check-prefix GLOBALCASE
// RUN: FileCheck %s --input-file %t/output-c.symbols.json --check-prefix GLOBALOTHERCASE
// RUN: FileCheck %s --input-file %t/output-cxx.symbols.json --check-prefix GLOBALCASE
// RUN: FileCheck %s --input-file %t/output-cxx.symbols.json --check-prefix GLOBALOTHERCASE
enum {
GlobalCase,
GlobalOtherCase
@@ -163,7 +178,8 @@ enum {
// GLOBALOTHERCASE-NEXT: "GlobalOtherCase"
// GLOBALOTHERCASE-NEXT: ]
// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix VEC
// RUN: FileCheck %s --input-file %t/output-c.symbols.json --check-prefix VEC
// RUN: FileCheck %s --input-file %t/output-cxx.symbols.json --check-prefix VEC
union Vector {
struct {
float X;

View File

@@ -1,8 +1,11 @@
// RUN: rm -rf %t
// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \
// RUN: --product-name=TypedefChain -triple arm64-apple-macosx -x c-header %s -o %t/typedefchain.symbols.json -verify
// RUN: --product-name=TypedefChain -triple arm64-apple-macosx -x c-header %s -o %t/typedefchain-c.symbols.json -verify
// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \
// RUN: --product-name=TypedefChain -triple arm64-apple-macosx -x c++-header %s -o %t/typedefchain-cxx.symbols.json -verify
// RUN: FileCheck %s --input-file %t/typedefchain.symbols.json --check-prefix MYSTRUCT
// RUN: FileCheck %s --input-file %t/typedefchain-c.symbols.json --check-prefix MYSTRUCT
// RUN: FileCheck %s --input-file %t/typedefchain-cxx.symbols.json --check-prefix MYSTRUCT
typedef struct { } MyStruct;
// MYSTRUCT-LABEL: "!testLabel": "c:@SA@MyStruct"
// MYSTRUCT: "accessLevel": "public",
@@ -34,7 +37,7 @@ typedef struct { } MyStruct;
// MYSTRUCT-NEXT: ]
// MYSTRUCT: "kind": {
// MYSTRUCT-NEXT: "displayName": "Structure",
// MYSTRUCT-NEXT: "identifier": "c.struct"
// MYSTRUCT-NEXT: "identifier": "c{{(\+\+)?}}.struct"
// MYSTRUCT: "names": {
// MYSTRUCT-NEXT: "navigator": [
// MYSTRUCT-NEXT: {
@@ -54,7 +57,8 @@ typedef struct { } MyStruct;
// MYSTRUCT-NEXT: "MyStruct"
// MYSTRUCT-NEXT: ]
// RUN: FileCheck %s --input-file %t/typedefchain.symbols.json --check-prefix MYSTRUCTSTRUCT
// RUN: FileCheck %s --input-file %t/typedefchain-c.symbols.json --check-prefix MYSTRUCTSTRUCT
// RUN: FileCheck %s --input-file %t/typedefchain-cxx.symbols.json --check-prefix MYSTRUCTSTRUCT
typedef MyStruct MyStructStruct;
// MYSTRUCTSTRUCT-LABEL: "!testLabel": "c:typedef_anonymous_record.c@T@MyStructStruct"
// MYSTRUCTSTRUCT: "accessLevel": "public",
@@ -87,10 +91,12 @@ typedef MyStruct MyStructStruct;
// MYSTRUCTSTRUCT-NEXT:],
// MYSTRUCTSTRUCT: "kind": {
// MYSTRUCTSTRUCT-NEXT: "displayName": "Type Alias",
// MYSTRUCTSTRUCT-NEXT: "identifier": "c.typealias"
// MYSTRUCTSTRUCT-NEXT: "identifier": "c{{(\+\+)?}}.typealias"
// RUN: FileCheck %s --input-file %t/typedefchain.symbols.json --check-prefix MYENUM
// RUN: FileCheck %s --input-file %t/typedefchain.symbols.json --check-prefix CASE
// RUN: FileCheck %s --input-file %t/typedefchain-c.symbols.json --check-prefix MYENUM
// RUN: FileCheck %s --input-file %t/typedefchain-c.symbols.json --check-prefix CASE
// RUN: FileCheck %s --input-file %t/typedefchain-cxx.symbols.json --check-prefix MYENUM
// RUN: FileCheck %s --input-file %t/typedefchain-cxx.symbols.json --check-prefix CASE
typedef enum { Case } MyEnum;
// MYENUM: "source": "c:@EA@MyEnum@Case",
// MYENUM-NEXT: "target": "c:@EA@MyEnum",
@@ -124,7 +130,7 @@ typedef enum { Case } MyEnum;
// MYENUM-NEXT:],
// MYENUM: "kind": {
// MYENUM-NEXT: "displayName": "Enumeration",
// MYENUM-NEXT: "identifier": "c.enum"
// MYENUM-NEXT: "identifier": "c{{(\+\+)?}}.enum"
// MYENUM: "names": {
// MYENUM-NEXT: "navigator": [
// MYENUM-NEXT: {
@@ -147,7 +153,8 @@ typedef enum { Case } MyEnum;
// CASE-NEXT: "Case"
// CASE-NEXT: ]
// RUN: FileCheck %s --input-file %t/typedefchain.symbols.json --check-prefix MYENUMENUM
// RUN: FileCheck %s --input-file %t/typedefchain-c.symbols.json --check-prefix MYENUMENUM
// RUN: FileCheck %s --input-file %t/typedefchain-cxx.symbols.json --check-prefix MYENUMENUM
typedef MyEnum MyEnumEnum;
// MYENUMENUM-LABEL: "!testLabel": "c:typedef_anonymous_record.c@T@MyEnumEnum"
// MYENUMENUM: "declarationFragments": [
@@ -179,7 +186,7 @@ typedef MyEnum MyEnumEnum;
// MYENUMENUM-NEXT: ],
// MYENUMENUM: "kind": {
// MYENUMENUM-NEXT: "displayName": "Type Alias",
// MYENUMENUM-NEXT: "identifier": "c.typealias"
// MYENUMENUM-NEXT: "identifier": "c{{(\+\+)?}}.typealias"
// MYENUMENUM-NEXT: },
// MYENUMENUM: "title": "MyEnumEnum"