Skip to content

Commit 3675d3f

Browse files
authored
Add support for dependent declaration names in rules (#227)
Adds support for rules such as the following: ```cpp template <typename T1> T1 &f2(const std::reference_wrapper<T1> &a0) { return a0.operator T1 &(); } ```
1 parent 7e67e00 commit 3675d3f

8 files changed

Lines changed: 328 additions & 24 deletions

File tree

cpp2rust/cpp_rule_preprocessor.cpp

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -469,21 +469,13 @@ class Callback : public clang::ast_matchers::MatchFinder::MatchCallback {
469469
return ctx.getCanonicalType(spec);
470470
}
471471

472-
clang::QualType
473-
getDefaultArg(clang::TemplateDecl *decl,
474-
const clang::TemplateTypeParmDecl *parm,
475-
llvm::ArrayRef<clang::TemplateArgument> currentArgs) {
476-
clang::QualType type = parm->getDefaultArgument().getArgument().getAsType();
477-
if (!type->isDependentType()) {
478-
return type;
479-
}
480-
481-
clang::Sema::InstantiatingTemplate Inst(*sema_, loc_, decl);
472+
clang::QualType getSubstType(const clang::Sema::InstantiatingTemplate &Inst,
473+
clang::QualType type,
474+
llvm::ArrayRef<clang::TemplateArgument> args) {
482475
assert(!Inst.isInvalid() && "Invalid instantiation context");
483-
484476
clang::MultiLevelTemplateArgumentList mtal;
485477
mtal.setKind(clang::TemplateSubstitutionKind::Rewrite);
486-
mtal.addOuterTemplateArguments(currentArgs);
478+
mtal.addOuterTemplateArguments(args);
487479

488480
clang::TypeSourceInfo *tsi =
489481
sema_->SubstType(sema_->Context.getTrivialTypeSourceInfo(type), mtal,
@@ -492,6 +484,19 @@ class Callback : public clang::ast_matchers::MatchFinder::MatchCallback {
492484
return tsi->getType();
493485
}
494486

487+
clang::QualType
488+
getDefaultArg(clang::TemplateDecl *decl,
489+
const clang::TemplateTypeParmDecl *parm,
490+
llvm::ArrayRef<clang::TemplateArgument> currentArgs) {
491+
clang::QualType type = parm->getDefaultArgument().getArgument().getAsType();
492+
if (!type->isDependentType()) {
493+
return type;
494+
}
495+
496+
const clang::Sema::InstantiatingTemplate Inst(*sema_, loc_, decl);
497+
return getSubstType(Inst, type, currentArgs);
498+
}
499+
495500
clang::VarDecl *createVarDecl(clang::QualType type, llvm::StringRef name,
496501
clang::StorageClass sclass = clang::SC_None) {
497502
clang::ASTContext &ctx = sema_->Context;
@@ -553,6 +558,10 @@ class Callback : public clang::ast_matchers::MatchFinder::MatchCallback {
553558
} else if (const auto *nttp =
554559
llvm::dyn_cast<clang::NonTypeTemplateParmDecl>(param)) {
555560
clang::QualType type = nttp->getType();
561+
if (type->isDependentType()) {
562+
const clang::Sema::InstantiatingTemplate Inst(*sema_, loc_, decl);
563+
type = getSubstType(Inst, type, out);
564+
}
556565
clang::DeclRefExpr *var =
557566
createConstexprDeclRefExpr(type, param->getName());
558567
out.emplace_back(var, true);
@@ -713,7 +722,7 @@ class Callback : public clang::ast_matchers::MatchFinder::MatchCallback {
713722
clang::TemplateArgumentListInfo explicitTArgs;
714723

715724
{
716-
clang::Sema::InstantiatingTemplate Inst(*sema_, loc_, decl);
725+
const clang::Sema::InstantiatingTemplate Inst(*sema_, loc_, decl);
717726
assert(!Inst.isInvalid() && "Invalid instantiation context");
718727
for (const auto &argloc : lookup.explicitArgs) {
719728
const auto &arg = argloc.getArgument();
@@ -724,16 +733,8 @@ class Callback : public clang::ast_matchers::MatchFinder::MatchCallback {
724733

725734
clang::TemplateArgument inst;
726735
if (arg.getKind() == clang::TemplateArgument::Type) {
727-
clang::QualType type = arg.getAsType();
728-
clang::MultiLevelTemplateArgumentList mtal;
729-
mtal.setKind(clang::TemplateSubstitutionKind::Rewrite);
730-
mtal.addOuterTemplateArguments(ruleTArgs);
731-
732-
clang::TypeSourceInfo *tsi =
733-
sema_->SubstType(sema_->Context.getTrivialTypeSourceInfo(type),
734-
mtal, loc_, clang::DeclarationName());
735-
assert(tsi && "Template argument type instantiation failed");
736-
inst = clang::TemplateArgument(tsi->getType());
736+
inst = clang::TemplateArgument(
737+
getSubstType(Inst, arg.getAsType(), ruleTArgs));
737738
} else if (arg.getKind() == clang::TemplateArgument::Expression) {
738739
if (auto *expr =
739740
llvm::dyn_cast<clang::DeclRefExpr>(arg.getAsExpr())) {
@@ -753,7 +754,17 @@ class Callback : public clang::ast_matchers::MatchFinder::MatchCallback {
753754
}
754755
}
755756

756-
clang::DeclarationName &name = lookup.name;
757+
clang::DeclarationName name = lookup.name;
758+
if (clang::QualType nameType = name.getCXXNameType();
759+
!nameType.isNull() && nameType->isDependentType()) {
760+
const clang::Sema::InstantiatingTemplate Inst(*sema_, loc_, decl);
761+
assert(!Inst.isInvalid() && "Invalid instantiation context");
762+
clang::MultiLevelTemplateArgumentList mtal;
763+
mtal.setKind(clang::TemplateSubstitutionKind::Rewrite);
764+
mtal.addOuterTemplateArguments(ruleTArgs);
765+
name = sema_->SubstDeclarationNameInfo({name, loc_}, mtal).getName();
766+
}
767+
757768
clang::OverloadCandidateSet candidates(loc_, csk);
758769
switch (lookup.kind) {
759770
case LookupKind::RegularName:

rules/functional/src.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright (c) 2022-present INESC-ID.
2+
// Distributed under the MIT license that can be found in the LICENSE file.
3+
4+
#include <functional>
5+
6+
template <typename T1> using t1 = std::reference_wrapper<T1>;
7+
8+
template <typename T1> std::reference_wrapper<T1> f1(T1 &a0) {
9+
return std::reference_wrapper<T1>(a0);
10+
}
11+
12+
template <typename T1> T1 &f2(const std::reference_wrapper<T1> &a0) {
13+
return a0.operator T1 &();
14+
}
15+
16+
template <typename T1> T1 &f3(const std::reference_wrapper<T1> &a0) {
17+
return a0.get();
18+
}

rules/functional/tgt_refcount.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright (c) 2022-present INESC-ID.
2+
// Distributed under the MIT license that can be found in the LICENSE file.
3+
4+
use libcc2rs::*;
5+
6+
fn t1<T1>() -> Ptr<T1> {
7+
Ptr::null()
8+
}
9+
10+
fn f1<T1>(a0: Ptr<T1>) -> Ptr<T1> {
11+
a0
12+
}
13+
14+
fn f2<T1>(a0: Ptr<T1>) -> Ptr<T1> {
15+
a0.clone()
16+
}
17+
18+
fn f3<T1>(a0: Ptr<T1>) -> Ptr<T1> {
19+
a0.clone()
20+
}

rules/functional/tgt_unsafe.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright (c) 2022-present INESC-ID.
2+
// Distributed under the MIT license that can be found in the LICENSE file.
3+
4+
fn t1<T1>() -> *mut T1 {
5+
Default::default()
6+
}
7+
8+
unsafe fn f1<T1>(a0: *mut T1) -> *mut T1 {
9+
a0
10+
}
11+
12+
unsafe fn f2<T1>(a0: *mut T1) -> *mut T1 {
13+
a0
14+
}
15+
16+
unsafe fn f3<T1>(a0: *mut T1) -> *mut T1 {
17+
a0
18+
}

rules/src/modules.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ pub mod fnmatch_tgt_unsafe;
4848
pub mod fstream_tgt_refcount;
4949
#[path = r#"../fstream/tgt_unsafe.rs"#]
5050
pub mod fstream_tgt_unsafe;
51+
#[path = r#"../functional/tgt_refcount.rs"#]
52+
pub mod functional_tgt_refcount;
53+
#[path = r#"../functional/tgt_unsafe.rs"#]
54+
pub mod functional_tgt_unsafe;
5155
#[path = r#"../ifaddrs/tgt_unsafe.rs"#]
5256
pub mod ifaddrs_tgt_unsafe;
5357
#[path = r#"../initializer_list/tgt_unsafe.rs"#]
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
extern crate libcc2rs;
2+
use libcc2rs::*;
3+
use std::cell::RefCell;
4+
use std::collections::BTreeMap;
5+
use std::io::prelude::*;
6+
use std::io::{Read, Seek, Write};
7+
use std::os::fd::AsFd;
8+
use std::rc::{Rc, Weak};
9+
#[derive(Default)]
10+
pub struct Point {
11+
pub x: Value<i32>,
12+
pub y: Value<i32>,
13+
}
14+
impl Clone for Point {
15+
fn clone(&self) -> Self {
16+
let mut this = Self {
17+
x: Rc::new(RefCell::new((*self.x.borrow()))),
18+
y: Rc::new(RefCell::new((*self.y.borrow()))),
19+
};
20+
this
21+
}
22+
}
23+
impl ByteRepr for Point {
24+
fn byte_size() -> usize {
25+
8
26+
}
27+
fn to_bytes(&self, buf: &mut [u8]) {
28+
(*self.x.borrow()).to_bytes(&mut buf[0..4]);
29+
(*self.y.borrow()).to_bytes(&mut buf[4..8]);
30+
}
31+
fn from_bytes(buf: &[u8]) -> Self {
32+
Self {
33+
x: Rc::new(RefCell::new(<i32>::from_bytes(&buf[0..4]))),
34+
y: Rc::new(RefCell::new(<i32>::from_bytes(&buf[4..8]))),
35+
}
36+
}
37+
}
38+
pub fn set_0(ref_: Ptr<i32>, val: i32) {
39+
let ref_: Value<Ptr<i32>> = Rc::new(RefCell::new(ref_));
40+
let val: Value<i32> = Rc::new(RefCell::new(val));
41+
(*ref_.borrow()).clone().write((*val.borrow()));
42+
}
43+
pub fn read_1(ref_: Ptr<i32>) -> i32 {
44+
let ref_: Value<Ptr<i32>> = Rc::new(RefCell::new(ref_));
45+
let r: Ptr<i32> = (*ref_.borrow()).clone();
46+
return (r.read());
47+
}
48+
pub fn main() {
49+
std::process::exit(main_0());
50+
}
51+
fn main_0() -> i32 {
52+
let i1: Value<i32> = Rc::new(RefCell::new(10));
53+
let ref_1: Value<Ptr<i32>> = Rc::new(RefCell::new(i1.as_pointer()));
54+
(*ref_1.borrow()).clone().write(20);
55+
let i2: Ptr<i32> = (*ref_1.borrow()).clone();
56+
{
57+
let _ptr = i2.clone();
58+
_ptr.write(_ptr.read() + 5)
59+
};
60+
write!(libcc2rs::cout(), "{:}\n", (*i1.borrow()),);
61+
let i3: Value<i32> = Rc::new(RefCell::new(1));
62+
let i4: Value<i32> = Rc::new(RefCell::new(2));
63+
let ref_3: Value<Ptr<i32>> = Rc::new(RefCell::new(i3.as_pointer()));
64+
let ref_4: Value<Ptr<i32>> = Rc::new(RefCell::new(i4.as_pointer()));
65+
let __rhs = ((*ref_4.borrow()).clone().read());
66+
(*ref_3.borrow()).clone().write(__rhs);
67+
write!(
68+
libcc2rs::cout(),
69+
"{:} {:}\n",
70+
(*i3.borrow()),
71+
(*i4.borrow()),
72+
);
73+
({ set_0((*ref_1.borrow()).clone(), 99) });
74+
write!(
75+
libcc2rs::cout(),
76+
"{:} {:}\n",
77+
(*i1.borrow()),
78+
({ read_1((*ref_1.borrow()).clone(),) }),
79+
);
80+
let point: Value<Point> = Rc::new(RefCell::new(Point {
81+
x: Rc::new(RefCell::new(3)),
82+
y: Rc::new(RefCell::new(4)),
83+
}));
84+
let point_ref: Value<Ptr<Point>> = Rc::new(RefCell::new(point.as_pointer()));
85+
(*(*(*point_ref.borrow()).clone().upgrade().deref())
86+
.x
87+
.borrow_mut()) = 30;
88+
(*(*(*point_ref.borrow()).clone().upgrade().deref())
89+
.y
90+
.borrow_mut()) = 40;
91+
write!(
92+
libcc2rs::cout(),
93+
"{:} {:}\n",
94+
(*(*point.borrow()).x.borrow()),
95+
(*(*point.borrow()).y.borrow()),
96+
);
97+
return 0;
98+
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
extern crate libc;
2+
use libc::*;
3+
extern crate libcc2rs;
4+
use libcc2rs::*;
5+
use std::collections::BTreeMap;
6+
use std::io::{Read, Seek, Write};
7+
use std::os::fd::{AsFd, FromRawFd, IntoRawFd};
8+
use std::rc::Rc;
9+
#[repr(C)]
10+
#[derive(Copy, Clone, Default)]
11+
pub struct Point {
12+
pub x: i32,
13+
pub y: i32,
14+
}
15+
pub unsafe fn set_0(mut ref_: *mut i32, mut val: i32) {
16+
(*ref_) = val;
17+
}
18+
pub unsafe fn read_1(mut ref_: *mut i32) -> i32 {
19+
let r: *mut i32 = ref_;
20+
return (*r);
21+
}
22+
pub fn main() {
23+
unsafe {
24+
std::process::exit(main_0() as i32);
25+
}
26+
}
27+
unsafe fn main_0() -> i32 {
28+
let mut i1: i32 = 10;
29+
let mut ref_1: *mut i32 = &mut i1;
30+
(*ref_1) = 20;
31+
let i2: *mut i32 = ref_1;
32+
(*i2) += 5;
33+
write!(
34+
std::fs::File::from_raw_fd(
35+
std::io::stdout()
36+
.as_fd()
37+
.try_clone_to_owned()
38+
.unwrap()
39+
.into_raw_fd(),
40+
),
41+
"{:}\n",
42+
i1,
43+
);
44+
let mut i3: i32 = 1;
45+
let mut i4: i32 = 2;
46+
let mut ref_3: *mut i32 = &mut i3;
47+
let mut ref_4: *mut i32 = &mut i4;
48+
(*ref_3) = (*ref_4);
49+
write!(
50+
std::fs::File::from_raw_fd(
51+
std::io::stdout()
52+
.as_fd()
53+
.try_clone_to_owned()
54+
.unwrap()
55+
.into_raw_fd(),
56+
),
57+
"{:} {:}\n",
58+
i3,
59+
i4,
60+
);
61+
(unsafe { set_0(ref_1.clone(), 99) });
62+
write!(
63+
std::fs::File::from_raw_fd(
64+
std::io::stdout()
65+
.as_fd()
66+
.try_clone_to_owned()
67+
.unwrap()
68+
.into_raw_fd(),
69+
),
70+
"{:} {:}\n",
71+
i1,
72+
(unsafe { read_1(ref_1.clone(),) }),
73+
);
74+
let mut point: Point = Point { x: 3, y: 4 };
75+
let mut point_ref: *mut Point = &mut point;
76+
(*point_ref).x = 30;
77+
(*point_ref).y = 40;
78+
write!(
79+
std::fs::File::from_raw_fd(
80+
std::io::stdout()
81+
.as_fd()
82+
.try_clone_to_owned()
83+
.unwrap()
84+
.into_raw_fd(),
85+
),
86+
"{:} {:}\n",
87+
point.x,
88+
point.y,
89+
);
90+
return 0;
91+
}

0 commit comments

Comments
 (0)